# Svrnty Theme System - Quick Reference ## Standard Color Access Pattern **ALWAYS use:** ```dart final colorScheme = Theme.of(context).colorScheme; // Primary UI colorScheme.primary // Primary brand color (Crimson Red) colorScheme.onPrimary // Text on primary (white/black depending on theme) // Secondary UI colorScheme.secondary // Secondary brand color (Slate Blue) colorScheme.onSecondary // Text on secondary // Text colorScheme.onSurface // Primary text colorScheme.onSurfaceVariant // Secondary text // Backgrounds colorScheme.surface // Page background colorScheme.surfaceContainer // Card background // Status (specialized) StatusColorScheme.getStatusColor(status) StatusColorScheme.getStatusColorFromTheme(status, colorScheme) // Theme-aware (preferred) ``` **NEVER use:** ```dart Colors.white // FORBIDDEN - use colorScheme.onPrimary or onSurface Colors.black // FORBIDDEN - use colorScheme.onSurface or scrim Color(0xFFXXXXXX) // FORBIDDEN in components (except in theme files) SvrntyColors.crimsonRed // FORBIDDEN - use colorScheme.primary instead ``` ## Theme Variants The app provides **2 theme variants**: ### Light Theme - **Background:** White (#FCFCFC) - **Primary:** Crimson Red (#C91F37) - high contrast variant - **Secondary:** Dark Slate (#2D3843) - high contrast variant - **Text:** Very dark gray (#1A1C1E) - 16.5:1 contrast (WCAG AAA) - **Secondary Text:** Dark gray (#3E4A56) - 7:1 contrast (WCAG AAA) ### Dark Theme (Forest Green) - **Background:** Dark Forest Green (#0C1410) - unique branding - **Primary:** Bright Crimson (#FF5A6D) - optimized for dark backgrounds - **Secondary:** Light Slate Gray (#A5B6C8) - **Text:** Pure white (#FFFFFF) - 18.2:1 contrast (WCAG AAA) - **Secondary Text:** Light gray-green (#E0E8E4) - 14.1:1 contrast (WCAG AAA) All text colors are WCAG AAA compliant (minimum 7:1 contrast for normal text, 4.5:1 for large text). ## Color Access Examples ### Good Examples ```dart // Text on colored background (e.g., status badge, avatar) Container( color: Theme.of(context).colorScheme.primary, child: Text( 'Label', style: TextStyle(color: Theme.of(context).colorScheme.onPrimary), ), ) // Primary text on page background Text( 'Hello', style: TextStyle(color: Theme.of(context).colorScheme.onSurface), ) // Secondary/muted text Text( 'Description', style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant), ) // Shadow color BoxShadow( color: Theme.of(context).colorScheme.scrim.withValues(alpha: 0.2), ) ``` ### Bad Examples (DON'T DO THIS) ```dart // WRONG - hardcoded white Text('Label', style: TextStyle(color: Colors.white)) // WRONG - hardcoded black BoxShadow(color: Colors.black.withValues(alpha: 0.2)) // WRONG - hardcoded color value Container(color: Color(0xFFFF9800)) // WRONG - using SvrntyColors directly for UI elements Container(color: SvrntyColors.crimsonRed) // Use colorScheme.primary instead ``` ## Status Colors For delivery status indicators, use the `StatusColorScheme` utility: ```dart import '../theme/status_colors.dart'; // Get status color (hardcoded, consistent across themes) final color = StatusColorScheme.getStatusColor('completed'); // Get status color from theme (preferred - adapts to theme) final themeColor = StatusColorScheme.getStatusColorFromTheme( 'completed', Theme.of(context).colorScheme, ); // Get background and text colors final bgColor = StatusColorScheme.getStatusBackground('completed'); final textColor = StatusColorScheme.getStatusText('completed'); // Use pre-built widgets StatusBadgeWidget(status: 'completed') StatusAccentBar(status: 'in_transit') ``` **Supported Status Values:** - `pending` - Amber (attention needed) - `in_transit`, `in_progress`, `processing` - Slate blue (active) - `completed`, `delivered`, `done` - Green (success) - `failed`, `error` - Red (problem) - `cancelled`, `skipped`, `rejected` - Gray (inactive) - `on_hold`, `paused`, `waiting` - Slate (informational) ## Progress Gradient Colors For progress indicators (e.g., route completion): ```dart import '../theme/color_system.dart'; // Progress colors (0-100%) SvrntyColors.progressLow // Orange - 0-40% SvrntyColors.progressMedium // Amber - 40-70% SvrntyColors.progressHigh // Green - 70-100% // Example: color interpolation Color progressColor = Color.lerp( SvrntyColors.progressLow, SvrntyColors.progressMedium, progressPercent, )!; ``` ## Modifying Colors ### Changing Brand Colors Edit the ColorScheme definitions in `/lib/theme.dart`: ```dart // Light theme static ColorScheme lightScheme() { return const ColorScheme( brightness: Brightness.light, primary: Color(0xffC91F37), // Change this for new primary color secondary: Color(0xff2D3843), // Change this for new secondary color // ... rest of colors ); } // Dark theme static ColorScheme darkScheme() { return const ColorScheme( brightness: Brightness.dark, primary: Color(0xffFF5A6D), // Change this for new primary color secondary: Color(0xffA5B6C8), // Change this for new secondary color // ... rest of colors ); } ``` ### Adding New Semantic Colors Add to `/lib/theme/color_system.dart`: ```dart class SvrntyColors { // ... existing colors /// New semantic color static const Color myNewColor = Color(0xFFXXXXXX); } ``` Then use it in components: ```dart Container(color: SvrntyColors.myNewColor) ``` ### Changing Status Colors Edit `/lib/theme/status_colors.dart`: ```dart class StatusColorScheme { static const Color completed = Color(0xFF22C55E); // Change this static const Color completedBackground = Color(0xFFD1FAE5); // Change this static const Color completedText = Color(0xFF065F46); // Change this // ... rest of colors } ``` ## Text Theme The app uses **Montserrat** font family for all text with explicit color assignments. **Font Weights:** - 300 (Light) - Unused in current design - 400 (Regular) - Body text - 500 (Medium) - Labels, buttons - 600 (SemiBold) - Headings, titles - 700 (Bold) - Display text, emphasis **Text Styles:** ```dart Theme.of(context).textTheme.displayLarge // 57px, bold, onSurface Theme.of(context).textTheme.headlineMedium // 28px, semibold, onSurface Theme.of(context).textTheme.titleLarge // 22px, semibold, onSurface Theme.of(context).textTheme.bodyMedium // 14px, regular, onSurface Theme.of(context).textTheme.labelSmall // 11px, medium, onSurfaceVariant ``` All text styles automatically adapt to light/dark themes with proper contrast. ## Accessibility All color combinations meet **WCAG AAA** standards (7:1 contrast for normal text, 4.5:1 for large text): **Light Theme:** - Primary text on background: 16.5:1 (WCAG AAA) - Secondary text on background: 7:1 (WCAG AAA) - Text on primary color: 6.2:1 (WCAG AA Large) **Dark Theme:** - Primary text on background: 18.2:1 (WCAG AAA) - Secondary text on background: 14.1:1 (WCAG AAA) - Text on primary color: 11.8:1 (WCAG AAA) ## Component Themes Component-specific theme configurations are in `/lib/theme/component_themes.dart`: - CardTheme - Elevated cards with subtle shadows - AppBarTheme - Navigation bars - ButtonTheme - Filled, outlined, elevated buttons - InputDecorationTheme - Text fields - SnackBarTheme - Toast messages - DialogTheme - Modal dialogs - BottomNavigationBarTheme - Bottom navigation - ChipTheme - Status chips - ProgressIndicatorTheme - Loading indicators - FloatingActionButtonTheme - FAB - SliderTheme - Range inputs All component themes use `ColorScheme` properties for consistency. ## Migration Guide If you need to migrate old hardcoded colors to the new theme system: ### Step 1: Find Hardcoded Colors ```bash # Search for hardcoded colors in your components grep -r "Colors\.white\|Colors\.black\|Color(0x" lib/components/ lib/pages/ ``` ### Step 2: Replace with Theme Colors | Old Pattern | New Pattern | |------------|-------------| | `Colors.white` on colored bg | `colorScheme.onPrimary` | | `Colors.white` on page | `colorScheme.surface` | | `Colors.black` for text | `colorScheme.onSurface` | | `Colors.black` for shadow | `colorScheme.scrim` | | `Color(0xFFXXXXXX)` | Use `colorScheme` or `SvrntyColors` | ### Step 3: Test Both Themes - Run app in light mode, verify all text is visible - Run app in dark mode, verify all text is visible - Check color contrast with browser dev tools ## Troubleshooting **Text not visible in dark mode:** - Ensure you're using `colorScheme.onSurface` or `onSurfaceVariant` for text colors - Don't use hardcoded `Colors.black` or dark colors for text - Check that TextTheme is properly applied with `_buildTextTheme()` **Colors not updating when switching themes:** - Use `Theme.of(context).colorScheme` instead of `SvrntyColors` constants - Ensure widget rebuilds when theme changes (use `ConsumerWidget` for Riverpod) - Avoid caching ColorScheme outside of build method **Wrong colors in components:** - Verify component uses `colorScheme` parameter correctly - Check that custom theme is applied in MaterialApp - Use `theme()` method to generate ThemeData ## Resources - **Material Design 3:** https://m3.material.io/ - **WCAG Contrast Checker:** https://webaim.org/resources/contrastchecker/ - **Flutter Theme Guide:** https://docs.flutter.dev/cookbook/design/themes - **ColorScheme Docs:** https://api.flutter.dev/flutter/material/ColorScheme-class.html