feat: add responsive abstract background shapes to all screens

This commit is contained in:
ssbg04 committed 2026-07-21 23:51:05 +08:00
1 parent 9a2386142f
commit afb4946fa9
4 files changed
+187 -5

No files matched your search

@@ -20,6 +20,7 @@ import '../providers/reports_provider.dart';
import '../providers/users_provider.dart';
import '../providers/auth_provider.dart';
import '../shared/dialogs/logout_dialog.dart';
import '../shared/widgets/abstract_background.dart';
import '../providers/navigation_provider.dart';
import '../shared/modals/capstone_members_modal.dart';
@@ -313,7 +314,8 @@ class _AndroidBottomNavLayoutState extends ConsumerState<AndroidBottomNavLayout>
),
),
),
body: Stack(
body: AbstractBackground(
child: Stack(
children: [
IndexedStack(
index: currentIndex,
@@ -332,6 +334,7 @@ class _AndroidBottomNavLayoutState extends ConsumerState<AndroidBottomNavLayout>
),
],
),
),
),
),
);
@@ -19,6 +19,7 @@ import '../providers/reports_provider.dart';
import '../providers/users_provider.dart';
import '../providers/auth_provider.dart';
import '../shared/dialogs/logout_dialog.dart';
import '../shared/widgets/abstract_background.dart';
import '../providers/navigation_provider.dart';
import 'dart:io' show Platform;
@@ -457,8 +458,9 @@ class _WindowsSidebarLayoutState extends ConsumerState<WindowsSidebarLayout> {
// MAIN CONTENT AREA
// ==========================================
Expanded(
child: Stack(
children: [
child: AbstractBackground(
child: Stack(
children: [
IndexedStack(
index: currentIndex,
children: tabs.asMap().entries.map((entry) {
@@ -477,6 +479,7 @@ class _WindowsSidebarLayoutState extends ConsumerState<WindowsSidebarLayout> {
],
),
),
),
],
),
),
@@ -15,6 +15,7 @@ import '../../providers/auth_provider.dart';
import 'package:frontend/ui/providers/navigation_provider.dart';
import '../../shared/dialogs/error_dialog.dart';
import '../../shared/dialogs/success_dialog.dart';
import '../../shared/widgets/abstract_background.dart';
import '../../../core/utils/validators.dart';
import '../../../core/network/api_constants.dart';
import '../../../core/network/server_discovery.dart';
@@ -176,7 +177,8 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
),
),
Expanded(
child: LayoutBuilder(
child: AbstractBackground(
child: LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth >= 800) {
// Desktop: Split Layout
@@ -282,7 +284,8 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
}
},
),
),
),
),
],
),
);
@@ -0,0 +1,173 @@
import 'dart:math' as math;
import 'package:flutter/material.dart';
import '../../../core/constants/app_colors.dart';
/// A lightweight, static abstract background decorator that adds subtle,
/// non-distracting geometric shapes to make screen backgrounds engaging.
/// Fully responsive across Mobile, Web, and Desktop platforms.
class AbstractBackground extends StatelessWidget {
final Widget child;
const AbstractBackground({
super.key,
required this.child,
});
@override
Widget build(BuildContext context) {
return Stack(
fit: StackFit.expand,
children: [
// Static abstract background shapes layer (Ignored for pointer events)
const IgnorePointer(
child: _AbstractShapesCanvas(),
),
// Screen Content Layer
child,
],
);
}
}
class _AbstractShapesCanvas extends StatelessWidget {
const _AbstractShapesCanvas();
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
final width = constraints.maxWidth;
final height = constraints.maxHeight;
if (width == 0 || height == 0) return const SizedBox.shrink();
return Stack(
children: [
// Base background tint
Container(color: AppColors.pageBackground),
// Shape 1: Top-Right Soft Circle Blob
Positioned(
top: -height * 0.08,
right: -width * 0.05,
child: Container(
width: math.max(180, width * 0.35),
height: math.max(180, width * 0.35),
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: RadialGradient(
colors: [
AppColors.primaryGreen.withValues(alpha: 0.07),
AppColors.primaryGreen.withValues(alpha: 0.0),
],
),
),
),
),
// Shape 2: Top-Left Tilted Rounded Rect
Positioned(
top: height * 0.12,
left: -width * 0.04,
child: Transform.rotate(
angle: -math.pi / 6,
child: Container(
width: math.max(140, width * 0.22),
height: math.max(70, width * 0.11),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24),
color: AppColors.darkGreen.withValues(alpha: 0.035),
),
),
),
),
// Shape 3: Middle-Left Outline Ring
Positioned(
top: height * 0.45,
left: width * 0.03,
child: Container(
width: math.max(80, width * 0.12),
height: math.max(80, width * 0.12),
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: AppColors.primaryGreen.withValues(alpha: 0.05),
width: 3,
),
),
),
),
// Shape 4: Bottom-Left Soft Radial Glow Blob
Positioned(
bottom: -height * 0.1,
left: -width * 0.08,
child: Container(
width: math.max(220, width * 0.4),
height: math.max(220, width * 0.4),
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: RadialGradient(
colors: [
AppColors.primaryGreen.withValues(alpha: 0.06),
AppColors.primaryGreen.withValues(alpha: 0.0),
],
),
),
),
),
// Shape 5: Bottom-Right Tilted Pill Capsule
Positioned(
bottom: height * 0.15,
right: -width * 0.03,
child: Transform.rotate(
angle: math.pi / 4,
child: Container(
width: math.max(160, width * 0.25),
height: math.max(60, width * 0.09),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: AppColors.primaryGreen.withValues(alpha: 0.04),
),
),
),
),
// Shape 6: Top-Center Subtle Dot Accent
Positioned(
top: height * 0.06,
left: width * 0.42,
child: Container(
width: 14,
height: 14,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: AppColors.primaryGreen.withValues(alpha: 0.06),
),
),
),
// Shape 7: Bottom-Center Small Rotated Square
Positioned(
bottom: height * 0.08,
left: width * 0.5,
child: Transform.rotate(
angle: math.pi / 8,
child: Container(
width: 22,
height: 22,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
color: AppColors.darkGreen.withValues(alpha: 0.04),
),
),
),
),
],
);
},
);
}
}