diff --git a/CLAUDE.md b/CLAUDE.md index cee65b6..60ff9cf 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -202,6 +202,62 @@ dev_dependencies: json_serializable: ^6.7.1 ``` +### color architecture system + +The application features a sophisticated centralized color management system built around the `ScoringColorScheme` class, providing consistent visual theming across all scoring components. + +**architecture overview**: +- centralized color definitions in `lib/config/constants/scoring_colors.dart` +- explicit background and text color pairs for every score value +- multiple color schemes: traditional (vibrant) and lowSaturation (muted) +- disabled state colors for conditional UI elements +- single source of truth for all score-related visual styling + +**color scheme structure**: +```dart +class ScoringColorScheme { + // Background colors for each score value + final Color goldRing; // X, 10, 9 + final Color redRing; // 8, 7 + final Color blueRing; // 6, 5 + final Color blackRing; // 4, 3 + final Color whiteRing; // 2, 1 + final Color miss; // M + final Color clear; // CLEAR button + + // Explicit text colors for each background + final Color goldText; // Black on gold for traditional + final Color redText; // White on red + final Color blueText; // White on blue + // ... etc for all combinations + + // Disabled state colors + final Color disabledBackground; + final Color disabledText; + final Color disabledBorder; +} +``` + +**usage patterns**: +```dart +// Get colors for any score value +Color bg = ScoringColors.getScoreBackgroundColor('X'); +Color text = ScoringColors.getScoreTextColor('X'); + +// Apply disabled styling for inactive elements +Color disabledBg = ScoringColors.getDisabledBackground(); +Color disabledText = ScoringColors.getDisabledText(); +``` + +**scheme switching**: +Change the active color scheme globally by updating `_currentScheme` in `scoring_colors.dart`. The traditional scheme uses vibrant archery target colors for high visibility, while lowSaturation provides muted tones for reduced eye strain during extended use. + +**disabled state implementation**: +The color system includes comprehensive disabled state support, used extensively for the sum of 6 column which remains visible but greyed out when in 3-arrow end mode. This maintains layout consistency while clearly indicating inactive functionality. + +**extensibility**: +The architecture is designed for easy expansion with additional color schemes such as high contrast, colorblind-friendly, or dark theme variants. Each scheme defines all required colors explicitly, preventing contrast issues and ensuring intentional design decisions. + ### code organization principles **separation of concerns**: diff --git a/lib/config/constants/_constants.md b/lib/config/constants/_constants.md index e3beb80..4fe54fb 100644 --- a/lib/config/constants/_constants.md +++ b/lib/config/constants/_constants.md @@ -1,48 +1,225 @@ -# Constants Directory +# constants configuration guide -This directory contains application-wide constants and configuration. +This directory contains the application's centralized constants and configuration system, providing consistent theming and behavior across all components. -## Files +## color scheme architecture -- **scoring_colors.dart**: Centralized color scheme system for all scoring-related UI components - - Provides multiple color schemes: `traditional` (vibrant) and `lowSaturation` (muted) - - Follows archery ring color conventions (gold, red, blue, black, white) - - Explicit text colors defined per scheme for intentional design control - - Disabled state colors for greying out inactive UI elements - - Single source of truth for all score-related colors with easy scheme switching - - Architecture ready for dark themes, high contrast, and colorblind-friendly schemes +The archery bookkeeper uses a sophisticated color system built around the `ScoringColorScheme` class, which provides complete visual consistency for all scoring-related UI components. -## Future Expansion +### available color schemes -Planned constants files: -- `app_constants.dart`: General app configuration (timeouts, limits, defaults) -- `layout_constants.dart`: UI spacing, sizing, and layout specifications -- `scoring_rules.dart`: Archery scoring rules and validation constants -- `export_constants.dart`: File formats, templates, and export configurations +**traditional scheme (default)**: +- vibrant, high-contrast colors matching classic archery target rings +- bright gold for X/10/9 scores, vivid red for 8/7, bright blue for 6/5 +- optimal for outdoor use and high visibility situations +- follows traditional archery color conventions -## Usage +**lowSaturation scheme**: +- muted, eye-friendly colors for reduced strain during long sessions +- same color mapping but with reduced saturation and softer tones +- ideal for indoor use or extended practice sessions +- maintains accessibility while being easier on the eyes + +### color system architecture + +Each color scheme defines explicit colors for: +- **background colors**: one for each score value (X, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, M, CLEAR) +- **text colors**: intentionally chosen for each background to ensure readability +- **border colors**: selection highlighting and default cell borders +- **disabled states**: greyed-out versions for inactive UI elements + +This architecture ensures: +- visual consistency across all scoring widgets +- easy theme switching without code changes +- proper text contrast on all backgrounds +- seamless disabled state handling for conditional UI elements + +### switching color schemes + +To change the active color scheme, edit the `_currentScheme` constant in `scoring_colors.dart`: + +```dart +// Use traditional vibrant colors +static const ScoringColorScheme _currentScheme = traditional; + +// Or switch to muted colors +static const ScoringColorScheme _currentScheme = lowSaturation; +``` + +The change applies instantly to all scoring components throughout the app. + +### disabled state system + +The color system includes dedicated disabled state colors that automatically grey out inactive elements while maintaining visual hierarchy: + +```dart +// Apply disabled styling to any widget +Container( + decoration: BoxDecoration( + color: ScoringColors.getDisabledBackground(), + border: Border.all( + color: ScoringColors.getDisabledBorder(), + width: 1.0, + ), + ), + child: Text( + 'Sum of 6', + style: TextStyle( + color: ScoringColors.getDisabledText(), + ), + ), +) +``` + +This is used extensively for the sum of 6 column, which remains visible but greyed out when in 3-arrow end mode. + +## usage patterns + +### basic color application ```dart import 'package:archery_bookkeeper/config/constants/scoring_colors.dart'; -// Get background color for any score (uses current active scheme) -Color bgColor = ScoringColors.getScoreBackgroundColor('X'); - -// Get appropriate text color with automatic contrast calculation +// Get colors for any score value +Color backgroundColor = ScoringColors.getScoreBackgroundColor('X'); Color textColor = ScoringColors.getScoreTextColor('X'); +bool shouldBeBold = ScoringColors.shouldUseBoldText('X'); -// Check if score should be bold -bool isBold = ScoringColors.shouldUseBoldText('10'); +// Apply to a widget +Container( + decoration: BoxDecoration( + color: backgroundColor, + border: Border.all( + color: ScoringColors.getBorderColor(isSelected), + width: ScoringColors.getBorderWidth(isSelected), + ), + ), + child: Text( + 'X', + style: TextStyle( + color: textColor, + fontWeight: shouldBeBold ? FontWeight.bold : FontWeight.normal, + ), + ), +) +``` -// Access available schemes +### conditional disabled states + +```dart +// Show as disabled when condition is false +Color bgColor = showColumn + ? ScoringColors.getScoreBackgroundColor('10') + : ScoringColors.getDisabledBackground(); + +Color textColor = showColumn + ? ScoringColors.getScoreTextColor('10') + : ScoringColors.getDisabledText(); +``` + +### accessing color schemes directly + +```dart +// Get the current active scheme +ScoringColorScheme current = ScoringColors.currentScheme; + +// Access specific schemes for comparison or settings UI ScoringColorScheme traditional = ScoringColors.availableTraditional; ScoringColorScheme lowSat = ScoringColors.availableLowSaturation; -// Get disabled state colors -Color disabledBg = ScoringColors.getDisabledBackground(); -Color disabledText = ScoringColors.getDisabledText(); -Color disabledBorder = ScoringColors.getDisabledBorder(); +// Use scheme properties directly +Color goldBackground = traditional.goldRing; +Color goldText = traditional.goldText; +``` -// Switch schemes by changing _currentScheme in scoring_colors.dart: -// static const ScoringColorScheme _currentScheme = lowSaturation; -``` \ No newline at end of file +## adding new color schemes + +To create additional color schemes (such as high contrast or colorblind-friendly variants): + +1. **define the new scheme** in `scoring_colors.dart`: + +```dart +static const ScoringColorScheme highContrast = ScoringColorScheme( + // Background colors - use high contrast values + goldRing: Color(0xFFFFFF00), // Pure yellow + redRing: Color(0xFFFF0000), // Pure red + blueRing: Color(0xFF0000FF), // Pure blue + blackRing: Color(0xFF000000), // Pure black + whiteRing: Color(0xFFFFFFFF), // Pure white + miss: Color(0xFF808080), // Medium grey + clear: Color(0xFFFF8000), // Orange + + // Text colors - ensure maximum contrast + goldText: Colors.black, + redText: Colors.white, + blueText: Colors.white, + blackText: Colors.white, + whiteText: Colors.black, + missText: Colors.black, + clearText: Colors.white, + + // Borders and disabled states + selectedBorder: Color(0xFF0080FF), + defaultBorder: Color(0xFF606060), + disabledBackground: Color(0xFFE0E0E0), + disabledText: Color(0xFF909090), + disabledBorder: Color(0xFFC0C0C0), +); +``` + +2. **add an accessor method**: + +```dart +static ScoringColorScheme get availableHighContrast => highContrast; +``` + +3. **switch to the new scheme** by updating `_currentScheme`: + +```dart +static const ScoringColorScheme _currentScheme = highContrast; +``` + +## future expansion possibilities + +The color system is designed for easy extension: + +- **dark theme support**: add dark background schemes with appropriate text colors +- **accessibility themes**: high contrast, large text, colorblind-friendly variants +- **user customization**: runtime scheme switching with settings persistence +- **seasonal themes**: holiday or event-specific color schemes +- **tournament modes**: competition-specific color coding + +### planned constants files + +Other constants modules planned for the application: + +- `app_constants.dart`: general app configuration (timeouts, limits, defaults) +- `layout_constants.dart`: UI spacing, sizing, and layout specifications +- `scoring_rules.dart`: archery scoring rules and validation constants +- `export_constants.dart`: file formats, templates, and export configurations + +## implementation notes + +### why explicit text colors? + +Instead of calculating text colors automatically, each scheme defines explicit text colors because: +- ensures intentional design decisions for every color combination +- prevents unexpected contrast issues when colors change +- allows for creative text color choices beyond simple black/white +- provides complete design control for complex color schemes + +### disabled state philosophy + +Disabled states maintain visual hierarchy while clearly indicating inactive status: +- elements remain visible to preserve layout and context +- consistent grey palette prevents confusion with active elements +- text remains readable while being clearly distinguished from active content +- used extensively in sum of 6 column when in 3-arrow end mode + +### performance considerations + +The color system is designed for performance: +- all colors are compile-time constants +- no runtime color calculations or theme switching overhead +- minimal method call overhead for color lookups +- ready for hot reload during development \ No newline at end of file