Implement light minimalistic tech redesign with Material 3

Complete transformation from dark to light theme with a professional,
tech-forward design system featuring:

- Material 3 theming with cyan-based color palette (#0891B2 primary)
- Inter font family integration via Google Fonts
- Comprehensive theme system (colors, spacing, typography, shadows)
- Responsive component redesign across all screens
- Enhanced UX with hover animations, Hero transitions, and shimmer loading
- Accessibility features (reduced motion support, high contrast)
- Clean architecture with zero hardcoded values

Theme System:
- Created app_colors.dart with semantic color constants
- Created app_spacing.dart with 8px base spacing scale
- Created app_theme.dart with complete Material 3 configuration
- Added shimmer_loading.dart for image loading states

UI Components Updated:
- Book cards with hover effects and Hero animations
- Bottom navigation with refined styling
- All screens migrated to theme-based colors and typography
- Forms and inputs using consistent design system

Documentation:
- Added REDESIGN_SUMMARY.md with complete implementation overview
- Added IMPLEMENTATION_CHECKLIST.md with detailed task completion status

All components now use centralized theme with no hardcoded values,
ensuring consistency and easy future customization.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-07 13:26:06 +06:00
parent 3004f712f3
commit 5c7b65a0d3
116 changed files with 8484 additions and 0 deletions

View File

@@ -0,0 +1,294 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'app_colors.dart';
import 'app_spacing.dart';
class AppTheme {
// Shadow helpers
static List<BoxShadow> get shadowSm => [
const BoxShadow(
color: AppColors.shadow,
blurRadius: 2,
offset: Offset(0, 1),
),
];
static List<BoxShadow> get shadowMd => [
const BoxShadow(
color: AppColors.shadowMedium,
blurRadius: 6,
offset: Offset(0, 4),
),
];
static List<BoxShadow> get shadowLg => [
const BoxShadow(
color: AppColors.shadowLarge,
blurRadius: 15,
offset: Offset(0, 10),
),
];
static List<BoxShadow> get shadowXl => [
const BoxShadow(
color: AppColors.shadowXLarge,
blurRadius: 25,
offset: Offset(0, 20),
),
];
static ThemeData lightTheme() {
final colorScheme = ColorScheme.light(
primary: AppColors.primary,
secondary: AppColors.secondary,
error: AppColors.error,
surface: AppColors.surface,
surfaceContainerHighest: AppColors.surfaceVariant,
onPrimary: Colors.white,
onSecondary: AppColors.textPrimary,
onError: Colors.white,
onSurface: AppColors.textPrimary,
outline: AppColors.outline,
outlineVariant: AppColors.outlineVariant,
shadow: AppColors.shadow,
primaryContainer: AppColors.secondary.withValues(alpha: 0.2),
onPrimaryContainer: AppColors.primary,
);
final textTheme = GoogleFonts.interTextTheme(
TextTheme(
// Display styles (32px, 28px)
displayLarge: TextStyle(
fontSize: 32,
fontWeight: FontWeight.w700,
color: colorScheme.onSurface,
height: 1.2,
),
displayMedium: TextStyle(
fontSize: 28,
fontWeight: FontWeight.w700,
color: colorScheme.onSurface,
height: 1.2,
),
// Headline styles (24px, 20px)
headlineLarge: TextStyle(
fontSize: 24,
fontWeight: FontWeight.w600,
color: colorScheme.onSurface,
height: 1.3,
),
headlineMedium: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
color: colorScheme.onSurface,
height: 1.3,
),
// Title styles (18px, 16px, 14px)
titleLarge: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
color: colorScheme.onSurface,
height: 1.4,
),
titleMedium: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: colorScheme.onSurface,
height: 1.4,
),
titleSmall: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: colorScheme.onSurface,
height: 1.4,
),
// Body styles (16px, 14px, 12px)
bodyLarge: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
color: colorScheme.onSurface,
height: 1.5,
),
bodyMedium: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400,
color: colorScheme.onSurface,
height: 1.5,
),
bodySmall: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w400,
color: colorScheme.onSurface,
height: 1.5,
),
// Label styles (14px, 12px, 10px)
labelLarge: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: colorScheme.onSurface,
height: 1.4,
),
labelMedium: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: colorScheme.onSurface,
height: 1.4,
),
labelSmall: TextStyle(
fontSize: 10,
fontWeight: FontWeight.w500,
color: colorScheme.onSurface,
height: 1.4,
),
),
);
return ThemeData(
useMaterial3: true,
colorScheme: colorScheme,
textTheme: textTheme,
scaffoldBackgroundColor: AppColors.background,
// AppBar theme
appBarTheme: AppBarTheme(
backgroundColor: AppColors.surface,
foregroundColor: colorScheme.onSurface,
elevation: 0,
centerTitle: false,
titleTextStyle: textTheme.headlineLarge,
),
// Card theme
cardTheme: CardThemeData(
color: AppColors.surface,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppSpacing.radiusMedium),
side: BorderSide(color: colorScheme.outline, width: 1),
),
margin: const EdgeInsets.all(AppSpacing.sm),
),
// Input decoration theme
inputDecorationTheme: InputDecorationTheme(
filled: true,
fillColor: AppColors.surface,
contentPadding: const EdgeInsets.symmetric(
horizontal: AppSpacing.md,
vertical: AppSpacing.md,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(AppSpacing.radiusMedium),
borderSide: BorderSide(color: colorScheme.outline),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(AppSpacing.radiusMedium),
borderSide: BorderSide(color: colorScheme.outline),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(AppSpacing.radiusMedium),
borderSide: BorderSide(color: colorScheme.primary, width: 2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(AppSpacing.radiusMedium),
borderSide: BorderSide(color: colorScheme.error),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(AppSpacing.radiusMedium),
borderSide: BorderSide(color: colorScheme.error, width: 2),
),
labelStyle: textTheme.labelMedium,
hintStyle: textTheme.bodyMedium?.copyWith(
color: colorScheme.onSurface.withValues(alpha: 0.5),
),
),
// Elevated button theme
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.success,
foregroundColor: Colors.white,
elevation: 0,
padding: const EdgeInsets.symmetric(
horizontal: AppSpacing.lg,
vertical: AppSpacing.md,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppSpacing.radiusMedium),
),
textStyle: textTheme.labelLarge,
),
),
// Outlined button theme
outlinedButtonTheme: OutlinedButtonThemeData(
style: OutlinedButton.styleFrom(
foregroundColor: colorScheme.primary,
side: BorderSide(color: colorScheme.outline),
padding: const EdgeInsets.symmetric(
horizontal: AppSpacing.lg,
vertical: AppSpacing.md,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppSpacing.radiusMedium),
),
textStyle: textTheme.labelLarge,
),
),
// Text button theme
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(
foregroundColor: colorScheme.primary,
padding: const EdgeInsets.symmetric(
horizontal: AppSpacing.md,
vertical: AppSpacing.sm,
),
textStyle: textTheme.labelLarge,
),
),
// FAB theme
floatingActionButtonTheme: FloatingActionButtonThemeData(
backgroundColor: AppColors.success,
foregroundColor: Colors.white,
elevation: 4,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppSpacing.radiusMedium),
),
),
// Bottom navigation bar theme
bottomNavigationBarTheme: BottomNavigationBarThemeData(
backgroundColor: AppColors.surface,
selectedItemColor: colorScheme.primary,
unselectedItemColor: colorScheme.onSurface.withValues(alpha: 0.6),
selectedLabelStyle: textTheme.labelSmall,
unselectedLabelStyle: textTheme.labelSmall,
type: BottomNavigationBarType.fixed,
elevation: 0,
),
// Icon theme
iconTheme: IconThemeData(color: colorScheme.onSurface, size: 24),
// Divider theme
dividerTheme: DividerThemeData(
color: colorScheme.outline,
thickness: 1,
space: 1,
),
);
}
// Placeholder for dark theme
static ThemeData darkTheme() {
return lightTheme(); // TODO: Implement dark theme in future
}
AppTheme._();
}