diff --git a/lib/colors.dart b/lib/colors.dart index a53a73f..5e26f5a 100644 --- a/lib/colors.dart +++ b/lib/colors.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; +// Legacy colors - kept for backward compatibility const Color fires50 = Color(0xFFFBE9E7); const Color fires100 = Color(0xFFFFCCBC); const Color fires300 = Color(0xFFFF8A65); @@ -8,4 +9,60 @@ const Color fires900 = Color(0xFFBF360C); const Color firesErrorRed = Color(0xFFDD2C00); const Color firesSurfaceWhite = fires50; -const Color firesBackgroundWhite = Colors.white; \ No newline at end of file +const Color firesBackgroundWhite = Colors.white; + +// ============================================================================ +// Material 3 Color Palette - Modern Warm Theme (Production) +// ============================================================================ + +// Primary Color - Deep Orange (fire theme) +const Color m3Primary = Color(0xFFE65100); // Deep Orange 900 +const Color m3OnPrimary = Color(0xFFFFFFFF); // White +const Color m3PrimaryContainer = Color(0xFFFFCC80); // Orange 200 +const Color m3OnPrimaryContainer = Color(0xFF5D2700); // Deep Brown + +// Secondary Color - Brown (earth tones) +const Color m3Secondary = Color(0xFF6D4C41); // Brown 600 +const Color m3OnSecondary = Color(0xFFFFFFFF); // White +const Color m3SecondaryContainer = Color(0xFFD7CCC8); // Brown 50 +const Color m3OnSecondaryContainer = Color(0xFF3E2723); // Deep Brown + +// Tertiary Color - Teal (complementary accent) +const Color m3Tertiary = Color(0xFF00695C); // Teal 800 +const Color m3OnTertiary = Color(0xFFFFFFFF); // White +const Color m3TertiaryContainer = Color(0xFFB2DFDB); // Teal 100 +const Color m3OnTertiaryContainer = Color(0xFF004D40); // Deep Teal + +// Error Colors +const Color m3Error = Color(0xFFDD2C00); // Red 800 +const Color m3OnError = Color(0xFFFFFFFF); // White +const Color m3ErrorContainer = Color(0xFFFFCDD2); // Red 100 +const Color m3OnErrorContainer = Color(0xFF5F2120); // Deep Red + +// Surface & Background +const Color m3Surface = Color(0xFFFFFBFE); // Almost white +const Color m3OnSurface = Color(0xFF201A18); // Almost black +const Color m3SurfaceVariant = Color(0xFFF5DED6); // Light brown +const Color m3OnSurfaceVariant = Color(0xFF52443D); // Medium brown + +const Color m3Background = Color(0xFFFFFBFE); // Almost white +const Color m3OnBackground = Color(0xFF201A18); // Almost black + +// Outline & Borders +const Color m3Outline = Color(0xFF85736B); // Gray-brown +const Color m3OutlineVariant = Color(0xFFD7C2B9); // Light gray-brown +const Color m3Shadow = Color(0xFF000000); // Black +const Color m3Scrim = Color(0xFF000000); // Black + +// ============================================================================ +// Material 3 Development Theme Colors (Dev Theme) +// ============================================================================ + +// Dev Primary - Pink (easy to identify dev builds) +const Color m3DevPrimary = Color(0xFFC2185B); // Pink 700 +const Color m3DevOnPrimary = Color(0xFFFFFFFF); // White +const Color m3DevPrimaryContainer = Color(0xFFF8BBD0); // Pink 100 +const Color m3DevOnPrimaryContainer = Color(0xFF7B0043); // Deep Pink + +// Dev theme uses same secondary, tertiary, and neutral colors as production +// Only primary is different for visual distinction diff --git a/lib/theme.dart b/lib/theme.dart index 9f7f902..95d71eb 100644 --- a/lib/theme.dart +++ b/lib/theme.dart @@ -5,22 +5,294 @@ import 'colors.dart'; final ThemeData firesTheme = _buildFiresTheme(); ThemeData _buildFiresTheme() { - final ThemeData base = ThemeData.light(); - return base.copyWith( - primaryColor: fires600, - scaffoldBackgroundColor: firesSurfaceWhite, - cardColor: firesBackgroundWhite, - textSelectionTheme: const TextSelectionThemeData(selectionColor: fires300), - colorScheme: const ColorScheme.light( - primary: fires600, - secondary: fires900, - error: firesErrorRed, - surface: firesSurfaceWhite, - onSurface: fires900, - onSecondary: Colors.white, + // Material 3 Color Scheme - Modern Warm Palette + const ColorScheme colorScheme = ColorScheme.light( + primary: m3Primary, + onPrimary: m3OnPrimary, + primaryContainer: m3PrimaryContainer, + onPrimaryContainer: m3OnPrimaryContainer, + secondary: m3Secondary, + onSecondary: m3OnSecondary, + secondaryContainer: m3SecondaryContainer, + onSecondaryContainer: m3OnSecondaryContainer, + tertiary: m3Tertiary, + onTertiary: m3OnTertiary, + tertiaryContainer: m3TertiaryContainer, + onTertiaryContainer: m3OnTertiaryContainer, + error: m3Error, + onError: m3OnError, + errorContainer: m3ErrorContainer, + onErrorContainer: m3OnErrorContainer, + surface: m3Surface, + onSurface: m3OnSurface, + surfaceVariant: m3SurfaceVariant, + onSurfaceVariant: m3OnSurfaceVariant, + outline: m3Outline, + outlineVariant: m3OutlineVariant, + ); + + return ThemeData( + useMaterial3: true, + colorScheme: colorScheme, + scaffoldBackgroundColor: m3Surface, + cardColor: m3Surface, + + // ======================================================================== + // TEXT THEMES - Material 3 Complete + // ======================================================================== + textTheme: TextTheme( + // Display styles - Large, prominent text + displayLarge: TextStyle( + fontSize: 57, + fontWeight: FontWeight.w400, + letterSpacing: -0.25, + color: colorScheme.onSurface, + ), + displayMedium: TextStyle( + fontSize: 45, + fontWeight: FontWeight.w400, + letterSpacing: 0, + color: colorScheme.onSurface, + ), + displaySmall: TextStyle( + fontSize: 36, + fontWeight: FontWeight.w400, + letterSpacing: 0, + color: colorScheme.onSurface, + ), + + // Headline styles - Important section titles + headlineLarge: TextStyle( + fontSize: 32, + fontWeight: FontWeight.w600, + letterSpacing: 0, + color: colorScheme.onSurface, + ), + headlineMedium: TextStyle( + fontSize: 28, + fontWeight: FontWeight.w600, + letterSpacing: 0, + color: colorScheme.onSurface, + ), + headlineSmall: TextStyle( + fontSize: 24, + fontWeight: FontWeight.w600, + letterSpacing: 0, + color: colorScheme.onSurface, + ), + + // Title styles - Subheadings + titleLarge: TextStyle( + fontSize: 22, + fontWeight: FontWeight.w500, + letterSpacing: 0, + color: colorScheme.onSurface, + ), + titleMedium: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + letterSpacing: 0.15, + color: colorScheme.onSurface, + ), + titleSmall: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + letterSpacing: 0.1, + color: colorScheme.onSurface, + ), + + // Body styles - Main content text + bodyLarge: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + letterSpacing: 0.5, + color: colorScheme.onSurface, + ), + bodyMedium: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + letterSpacing: 0.25, + color: colorScheme.onSurface, + ), + bodySmall: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w400, + letterSpacing: 0.4, + color: colorScheme.onSurfaceVariant, + ), + + // Label styles - Buttons, badges, labels + labelLarge: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + letterSpacing: 0.1, + color: colorScheme.onSurface, + ), + labelMedium: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + letterSpacing: 0.5, + color: colorScheme.onSurface, + ), + labelSmall: TextStyle( + fontSize: 11, + fontWeight: FontWeight.w500, + letterSpacing: 0.5, + color: colorScheme.onSurface, + ), ), - //TODO: Add the text themes (103) - //TODO: Add the icon themes (103) - //TODO: Decorate the inputs (103) + + // ======================================================================== + // ICON THEMES + // ======================================================================== + iconTheme: IconThemeData( + color: colorScheme.primary, + size: 24, + ), + appBarTheme: AppBarTheme( + backgroundColor: colorScheme.primary, + foregroundColor: colorScheme.onPrimary, + elevation: 4, + shadowColor: colorScheme.shadow, + surfaceTintColor: colorScheme.primary, + iconTheme: IconThemeData(color: colorScheme.onPrimary), + titleTextStyle: TextStyle( + color: colorScheme.onPrimary, + fontSize: 20, + fontWeight: FontWeight.w500, + ), + ), + + // ======================================================================== + // INPUT DECORATION - Material 3 Filled Style + // ======================================================================== + inputDecorationTheme: InputDecorationTheme( + filled: true, + fillColor: colorScheme.surfaceVariant.withValues(alpha: 0.5), + isDense: false, + contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + + // Enabled state + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: colorScheme.outline, width: 1), + ), + + // Focused state + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: colorScheme.primary, width: 2), + ), + + // Error state + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: colorScheme.error, width: 1), + ), + focusedErrorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: colorScheme.error, width: 2), + ), + + // Label and hint styles + labelStyle: TextStyle( + color: colorScheme.primary, + fontSize: 14, + fontWeight: FontWeight.w500, + ), + hintStyle: TextStyle( + color: colorScheme.onSurfaceVariant, + fontSize: 14, + ), + + // Error text style + errorStyle: TextStyle( + color: colorScheme.error, + fontSize: 12, + ), + ), + + // ======================================================================== + // BUTTON THEMES + // ======================================================================== + elevatedButtonTheme: ElevatedButtonThemeData( + style: ElevatedButton.styleFrom( + backgroundColor: colorScheme.primary, + foregroundColor: colorScheme.onPrimary, + elevation: 4, + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + textStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600), + ), + ), + outlinedButtonTheme: OutlinedButtonThemeData( + style: OutlinedButton.styleFrom( + backgroundColor: colorScheme.surface, + foregroundColor: colorScheme.primary, + side: BorderSide(color: colorScheme.outline, width: 1), + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + textStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600), + ), + ), + textButtonTheme: TextButtonThemeData( + style: TextButton.styleFrom( + backgroundColor: Colors.transparent, + foregroundColor: colorScheme.primary, + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + textStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600), + ), + ), + + // ======================================================================== + // FLOATING ACTION BUTTON THEME + // ======================================================================== + floatingActionButtonTheme: FloatingActionButtonThemeData( + backgroundColor: colorScheme.primary, + foregroundColor: colorScheme.onPrimary, + elevation: 6, + focusElevation: 8, + hoverElevation: 8, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), + + // ======================================================================== + // CARD THEME + // ======================================================================== + cardTheme: CardThemeData( + color: colorScheme.surface, + elevation: 1, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + margin: const EdgeInsets.all(8), + shadowColor: colorScheme.shadow, + ), + + // ======================================================================== + // BOTTOM APP BAR THEME + // ======================================================================== + bottomAppBarTheme: BottomAppBarThemeData( + color: colorScheme.surface, + elevation: 4, + shadowColor: colorScheme.shadow, + surfaceTintColor: colorScheme.surface, + shape: const CircularNotchedRectangle(), + ), + + // ======================================================================== + // TEXT SELECTION THEME + // ======================================================================== + textSelectionTheme: TextSelectionThemeData( + cursorColor: colorScheme.primary, + selectionColor: colorScheme.primary.withValues(alpha: 0.3), + selectionHandleColor: colorScheme.primary, + ), + + // ======================================================================== + // ADDITIONAL THEMES + // ======================================================================== + canvasColor: colorScheme.surface, ); } diff --git a/lib/themeDev.dart b/lib/themeDev.dart index 47a1ac0..0eaea99 100644 --- a/lib/themeDev.dart +++ b/lib/themeDev.dart @@ -5,22 +5,295 @@ import 'colors.dart'; final ThemeData devFiresTheme = _buildFiresTheme(); ThemeData _buildFiresTheme() { - final ThemeData base = ThemeData.light(); - return base.copyWith( - primaryColor: Colors.pink, - scaffoldBackgroundColor: firesSurfaceWhite, - cardColor: firesBackgroundWhite, - textSelectionTheme: const TextSelectionThemeData(selectionColor: fires300), - colorScheme: const ColorScheme.light( - primary: Colors.pink, - secondary: fires900, - error: firesErrorRed, - surface: firesSurfaceWhite, - onSurface: fires900, - onSecondary: Colors.white, + // Material 3 Color Scheme - Development Theme with Pink Primary + // Uses pink for easy visual identification of dev builds + const ColorScheme colorScheme = ColorScheme.light( + primary: m3DevPrimary, + onPrimary: m3DevOnPrimary, + primaryContainer: m3DevPrimaryContainer, + onPrimaryContainer: m3DevOnPrimaryContainer, + secondary: m3Secondary, + onSecondary: m3OnSecondary, + secondaryContainer: m3SecondaryContainer, + onSecondaryContainer: m3OnSecondaryContainer, + tertiary: m3Tertiary, + onTertiary: m3OnTertiary, + tertiaryContainer: m3TertiaryContainer, + onTertiaryContainer: m3OnTertiaryContainer, + error: m3Error, + onError: m3OnError, + errorContainer: m3ErrorContainer, + onErrorContainer: m3OnErrorContainer, + surface: m3Surface, + onSurface: m3OnSurface, + surfaceVariant: m3SurfaceVariant, + onSurfaceVariant: m3OnSurfaceVariant, + outline: m3Outline, + outlineVariant: m3OutlineVariant, + ); + + return ThemeData( + useMaterial3: true, + colorScheme: colorScheme, + scaffoldBackgroundColor: m3Surface, + cardColor: m3Surface, + + // ======================================================================== + // TEXT THEMES - Material 3 Complete + // ======================================================================== + textTheme: TextTheme( + // Display styles - Large, prominent text + displayLarge: TextStyle( + fontSize: 57, + fontWeight: FontWeight.w400, + letterSpacing: -0.25, + color: colorScheme.onSurface, + ), + displayMedium: TextStyle( + fontSize: 45, + fontWeight: FontWeight.w400, + letterSpacing: 0, + color: colorScheme.onSurface, + ), + displaySmall: TextStyle( + fontSize: 36, + fontWeight: FontWeight.w400, + letterSpacing: 0, + color: colorScheme.onSurface, + ), + + // Headline styles - Important section titles + headlineLarge: TextStyle( + fontSize: 32, + fontWeight: FontWeight.w600, + letterSpacing: 0, + color: colorScheme.onSurface, + ), + headlineMedium: TextStyle( + fontSize: 28, + fontWeight: FontWeight.w600, + letterSpacing: 0, + color: colorScheme.onSurface, + ), + headlineSmall: TextStyle( + fontSize: 24, + fontWeight: FontWeight.w600, + letterSpacing: 0, + color: colorScheme.onSurface, + ), + + // Title styles - Subheadings + titleLarge: TextStyle( + fontSize: 22, + fontWeight: FontWeight.w500, + letterSpacing: 0, + color: colorScheme.onSurface, + ), + titleMedium: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + letterSpacing: 0.15, + color: colorScheme.onSurface, + ), + titleSmall: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + letterSpacing: 0.1, + color: colorScheme.onSurface, + ), + + // Body styles - Main content text + bodyLarge: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + letterSpacing: 0.5, + color: colorScheme.onSurface, + ), + bodyMedium: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + letterSpacing: 0.25, + color: colorScheme.onSurface, + ), + bodySmall: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w400, + letterSpacing: 0.4, + color: colorScheme.onSurfaceVariant, + ), + + // Label styles - Buttons, badges, labels + labelLarge: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + letterSpacing: 0.1, + color: colorScheme.onSurface, + ), + labelMedium: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + letterSpacing: 0.5, + color: colorScheme.onSurface, + ), + labelSmall: TextStyle( + fontSize: 11, + fontWeight: FontWeight.w500, + letterSpacing: 0.5, + color: colorScheme.onSurface, + ), ), - //TODO: Add the text themes (103) - //TODO: Add the icon themes (103) - //TODO: Decorate the inputs (103) + + // ======================================================================== + // ICON THEMES + // ======================================================================== + iconTheme: IconThemeData( + color: colorScheme.primary, + size: 24, + ), + appBarTheme: AppBarTheme( + backgroundColor: colorScheme.primary, + foregroundColor: colorScheme.onPrimary, + elevation: 4, + shadowColor: colorScheme.shadow, + surfaceTintColor: colorScheme.primary, + iconTheme: IconThemeData(color: colorScheme.onPrimary), + titleTextStyle: TextStyle( + color: colorScheme.onPrimary, + fontSize: 20, + fontWeight: FontWeight.w500, + ), + ), + + // ======================================================================== + // INPUT DECORATION - Material 3 Filled Style + // ======================================================================== + inputDecorationTheme: InputDecorationTheme( + filled: true, + fillColor: colorScheme.surfaceVariant.withValues(alpha: 0.5), + isDense: false, + contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + + // Enabled state + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: colorScheme.outline, width: 1), + ), + + // Focused state + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: colorScheme.primary, width: 2), + ), + + // Error state + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: colorScheme.error, width: 1), + ), + focusedErrorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: colorScheme.error, width: 2), + ), + + // Label and hint styles + labelStyle: TextStyle( + color: colorScheme.primary, + fontSize: 14, + fontWeight: FontWeight.w500, + ), + hintStyle: TextStyle( + color: colorScheme.onSurfaceVariant, + fontSize: 14, + ), + + // Error text style + errorStyle: TextStyle( + color: colorScheme.error, + fontSize: 12, + ), + ), + + // ======================================================================== + // BUTTON THEMES + // ======================================================================== + elevatedButtonTheme: ElevatedButtonThemeData( + style: ElevatedButton.styleFrom( + backgroundColor: colorScheme.primary, + foregroundColor: colorScheme.onPrimary, + elevation: 4, + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + textStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600), + ), + ), + outlinedButtonTheme: OutlinedButtonThemeData( + style: OutlinedButton.styleFrom( + backgroundColor: colorScheme.surface, + foregroundColor: colorScheme.primary, + side: BorderSide(color: colorScheme.outline, width: 1), + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + textStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600), + ), + ), + textButtonTheme: TextButtonThemeData( + style: TextButton.styleFrom( + backgroundColor: Colors.transparent, + foregroundColor: colorScheme.primary, + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + textStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600), + ), + ), + + // ======================================================================== + // FLOATING ACTION BUTTON THEME + // ======================================================================== + floatingActionButtonTheme: FloatingActionButtonThemeData( + backgroundColor: colorScheme.primary, + foregroundColor: colorScheme.onPrimary, + elevation: 6, + focusElevation: 8, + hoverElevation: 8, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), + + // ======================================================================== + // CARD THEME + // ======================================================================== + cardTheme: CardThemeData( + color: colorScheme.surface, + elevation: 1, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + margin: const EdgeInsets.all(8), + shadowColor: colorScheme.shadow, + ), + + // ======================================================================== + // BOTTOM APP BAR THEME + // ======================================================================== + bottomAppBarTheme: BottomAppBarThemeData( + color: colorScheme.surface, + elevation: 4, + shadowColor: colorScheme.shadow, + surfaceTintColor: colorScheme.surface, + shape: const CircularNotchedRectangle(), + ), + + // ======================================================================== + // TEXT SELECTION THEME + // ======================================================================== + textSelectionTheme: TextSelectionThemeData( + cursorColor: colorScheme.primary, + selectionColor: colorScheme.primary.withValues(alpha: 0.3), + selectionHandleColor: colorScheme.primary, + ), + + // ======================================================================== + // ADDITIONAL THEMES + // ======================================================================== + canvasColor: colorScheme.surface, ); }