Material 3

This commit is contained in:
vjrj 2026-03-06 22:28:42 +01:00
parent 7812ed951e
commit 7dcb8557c6
3 changed files with 635 additions and 33 deletions

View file

@ -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;
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

View file

@ -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,
);
}

View file

@ -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,
);
}