- Overhaul theme system with Svrnty design and WCAG AAA compliance - Remove android, macos, and web platform files (iOS-only focus) - Update components with improved dark mode map and UI refinements - Enhance settings page with additional configuration options - Add theme system documentation in lib/theme/README.md - Update CLAUDE.md with comprehensive theme guidelines Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
260 lines
9.2 KiB
Dart
260 lines
9.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'theme/component_themes.dart';
|
|
|
|
class MaterialTheme {
|
|
final TextTheme textTheme;
|
|
|
|
const MaterialTheme(this.textTheme);
|
|
|
|
// Svrnty Brand Colors - Light Theme (Enhanced Contrast)
|
|
static ColorScheme lightScheme() {
|
|
return const ColorScheme(
|
|
brightness: Brightness.light,
|
|
primary: Color(0xffC91F37), // Darker Crimson Red for better contrast
|
|
surfaceTint: Color(0xffC91F37),
|
|
onPrimary: Color(0xffffffff),
|
|
primaryContainer: Color(0xffFFE5E9),
|
|
onPrimaryContainer: Color(0xff2D0009),
|
|
secondary: Color(0xff2D3843), // Darker Slate for better contrast
|
|
onSecondary: Color(0xffffffff),
|
|
secondaryContainer: Color(0xffE0E7EE),
|
|
onSecondaryContainer: Color(0xff0A0F15),
|
|
tertiary: Color(0xff16803D), // Darker Green for contrast
|
|
onTertiary: Color(0xffffffff),
|
|
tertiaryContainer: Color(0xffD1F4DD),
|
|
onTertiaryContainer: Color(0xff00210B),
|
|
error: Color(0xffD32F2F),
|
|
onError: Color(0xffffffff),
|
|
errorContainer: Color(0xffFFEBEE),
|
|
onErrorContainer: Color(0xff5F0000),
|
|
surface: Color(0xffFCFCFC),
|
|
onSurface: Color(0xff1A1C1E), // Very dark gray for maximum contrast
|
|
onSurfaceVariant: Color(0xff3E4A56), // Darker gray for secondary text (7:1 contrast)
|
|
outline: Color(0xff5F6B77), // Darker outline (4.5:1 contrast)
|
|
outlineVariant: Color(0xffC4C7CC),
|
|
shadow: Color(0x1F000000),
|
|
scrim: Color(0xff000000),
|
|
inverseSurface: Color(0xff1A1C1E),
|
|
inversePrimary: Color(0xffFF6B7D),
|
|
primaryFixed: Color(0xffFFE5E9),
|
|
onPrimaryFixed: Color(0xff2D0009),
|
|
primaryFixedDim: Color(0xffFFB3C0),
|
|
onPrimaryFixedVariant: Color(0xff8B1A2A),
|
|
secondaryFixed: Color(0xffE0E7EE),
|
|
onSecondaryFixed: Color(0xff0A0F15),
|
|
secondaryFixedDim: Color(0xffA8B8C8),
|
|
onSecondaryFixedVariant: Color(0xff2D3843),
|
|
tertiaryFixed: Color(0xffD1F4DD),
|
|
onTertiaryFixed: Color(0xff00210B),
|
|
tertiaryFixedDim: Color(0xff9FD8B1),
|
|
onTertiaryFixedVariant: Color(0xff16803D),
|
|
surfaceDim: Color(0xffDEE1E4),
|
|
surfaceBright: Color(0xffFCFCFC),
|
|
surfaceContainerLowest: Color(0xffffffff),
|
|
surfaceContainerLow: Color(0xffF5F6F7),
|
|
surfaceContainer: Color(0xffEFF1F3),
|
|
surfaceContainerHigh: Color(0xffE9EBED),
|
|
surfaceContainerHighest: Color(0xffE3E5E8),
|
|
);
|
|
}
|
|
|
|
ThemeData light() {
|
|
return theme(lightScheme());
|
|
}
|
|
|
|
// Svrnty Brand Colors - Dark Theme (Forest Green with Maximum Contrast)
|
|
static ColorScheme darkScheme() {
|
|
return const ColorScheme(
|
|
brightness: Brightness.dark,
|
|
primary: Color(0xffFF5A6D), // Bright Crimson Red for dark mode
|
|
surfaceTint: Color(0xff4ADE80), // Success Green tint
|
|
onPrimary: Color(0xff000000), // Black text on bright primary
|
|
primaryContainer: Color(0xff9C1A29),
|
|
onPrimaryContainer: Color(0xffFFE5E8),
|
|
secondary: Color(0xffA5B6C8), // Very light Slate Gray
|
|
onSecondary: Color(0xff0C1410),
|
|
secondaryContainer: Color(0xff3A4958),
|
|
onSecondaryContainer: Color(0xffF2F6FA),
|
|
tertiary: Color(0xff5EE890), // Bright Success Green
|
|
onTertiary: Color(0xff003916),
|
|
tertiaryContainer: Color(0xff15803D),
|
|
onTertiaryContainer: Color(0xffE6FFF0),
|
|
error: Color(0xffFF8A80),
|
|
onError: Color(0xff000000),
|
|
errorContainer: Color(0xffB3261E),
|
|
onErrorContainer: Color(0xffFFEDEA),
|
|
surface: Color(0xff0C1410), // Dark Forest Green Background
|
|
onSurface: Color(0xffFFFFFF), // Pure white for primary text - maximum contrast
|
|
onSurfaceVariant: Color(0xffE0E8E4), // Very light gray-green for secondary text (much brighter)
|
|
outline: Color(0xffA5B5AB), // Light gray-green outline
|
|
outlineVariant: Color(0xff4A5A52),
|
|
shadow: Color(0xff000000),
|
|
scrim: Color(0xff000000),
|
|
inverseSurface: Color(0xffF0F4F2),
|
|
inversePrimary: Color(0xffDF2D45),
|
|
primaryFixed: Color(0xffFFE5E8),
|
|
onPrimaryFixed: Color(0xff3D0009),
|
|
primaryFixedDim: Color(0xffFF6B7D),
|
|
onPrimaryFixedVariant: Color(0xff9C1A29),
|
|
secondaryFixed: Color(0xffE8EEF3),
|
|
onSecondaryFixed: Color(0xff0A0F15),
|
|
secondaryFixedDim: Color(0xffA5B6C8),
|
|
onSecondaryFixedVariant: Color(0xff3A4958),
|
|
tertiaryFixed: Color(0xffE6FFF0),
|
|
onTertiaryFixed: Color(0xff003916),
|
|
tertiaryFixedDim: Color(0xff5EE890),
|
|
onTertiaryFixedVariant: Color(0xff15803D),
|
|
surfaceDim: Color(0xff08100D), // Darker forest green
|
|
surfaceBright: Color(0xff1F2D25), // Lighter forest green
|
|
surfaceContainerLowest: Color(0xff060D0A), // Deepest forest
|
|
surfaceContainerLow: Color(0xff141B18), // Low forest
|
|
surfaceContainer: Color(0xff18221D), // Mid forest green
|
|
surfaceContainerHigh: Color(0xff1D2822), // High forest
|
|
surfaceContainerHighest: Color(0xff2A3832), // Highest forest green (lighter)
|
|
);
|
|
}
|
|
|
|
ThemeData dark() {
|
|
return theme(darkScheme());
|
|
}
|
|
|
|
TextTheme _buildTextTheme(ColorScheme colorScheme) {
|
|
return TextTheme(
|
|
displayLarge: TextStyle(
|
|
fontFamily: 'Montserrat',
|
|
fontWeight: FontWeight.w700,
|
|
fontSize: 57,
|
|
letterSpacing: -0.5,
|
|
color: colorScheme.onSurface,
|
|
),
|
|
displayMedium: TextStyle(
|
|
fontFamily: 'Montserrat',
|
|
fontWeight: FontWeight.w700,
|
|
fontSize: 45,
|
|
letterSpacing: -0.5,
|
|
color: colorScheme.onSurface,
|
|
),
|
|
displaySmall: TextStyle(
|
|
fontFamily: 'Montserrat',
|
|
fontWeight: FontWeight.w700,
|
|
fontSize: 36,
|
|
letterSpacing: -0.25,
|
|
color: colorScheme.onSurface,
|
|
),
|
|
headlineLarge: TextStyle(
|
|
fontFamily: 'Montserrat',
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 32,
|
|
letterSpacing: -0.25,
|
|
color: colorScheme.onSurface,
|
|
),
|
|
headlineMedium: TextStyle(
|
|
fontFamily: 'Montserrat',
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 28,
|
|
letterSpacing: 0,
|
|
color: colorScheme.onSurface,
|
|
),
|
|
headlineSmall: TextStyle(
|
|
fontFamily: 'Montserrat',
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 24,
|
|
letterSpacing: 0,
|
|
color: colorScheme.onSurface,
|
|
),
|
|
titleLarge: TextStyle(
|
|
fontFamily: 'Montserrat',
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 22,
|
|
letterSpacing: 0,
|
|
color: colorScheme.onSurface,
|
|
),
|
|
titleMedium: TextStyle(
|
|
fontFamily: 'Montserrat',
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 16,
|
|
letterSpacing: 0.15,
|
|
color: colorScheme.onSurface,
|
|
),
|
|
titleSmall: TextStyle(
|
|
fontFamily: 'Montserrat',
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 14,
|
|
letterSpacing: 0.1,
|
|
color: colorScheme.onSurfaceVariant,
|
|
),
|
|
bodyLarge: TextStyle(
|
|
fontFamily: 'Montserrat',
|
|
fontWeight: FontWeight.w500,
|
|
fontSize: 16,
|
|
letterSpacing: 0.5,
|
|
color: colorScheme.onSurface,
|
|
),
|
|
bodyMedium: TextStyle(
|
|
fontFamily: 'Montserrat',
|
|
fontWeight: FontWeight.w500,
|
|
fontSize: 14,
|
|
letterSpacing: 0.25,
|
|
color: colorScheme.onSurface,
|
|
),
|
|
bodySmall: TextStyle(
|
|
fontFamily: 'Montserrat',
|
|
fontWeight: FontWeight.w500,
|
|
fontSize: 12,
|
|
letterSpacing: 0.4,
|
|
color: colorScheme.onSurfaceVariant,
|
|
),
|
|
labelLarge: TextStyle(
|
|
fontFamily: 'Montserrat',
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 14,
|
|
letterSpacing: 0.1,
|
|
color: colorScheme.onSurface,
|
|
),
|
|
labelMedium: TextStyle(
|
|
fontFamily: 'Montserrat',
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 12,
|
|
letterSpacing: 0.5,
|
|
color: colorScheme.onSurfaceVariant,
|
|
),
|
|
labelSmall: TextStyle(
|
|
fontFamily: 'Montserrat',
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 11,
|
|
letterSpacing: 0.5,
|
|
color: colorScheme.onSurfaceVariant,
|
|
),
|
|
);
|
|
}
|
|
|
|
ThemeData theme(ColorScheme colorScheme) {
|
|
return ThemeData(
|
|
useMaterial3: true,
|
|
brightness: colorScheme.brightness,
|
|
colorScheme: colorScheme,
|
|
fontFamily: 'Montserrat',
|
|
scaffoldBackgroundColor: colorScheme.surface,
|
|
canvasColor: colorScheme.surface,
|
|
textTheme: _buildTextTheme(colorScheme),
|
|
// Component Themes
|
|
cardTheme: ComponentThemes.cardTheme(colorScheme),
|
|
appBarTheme: ComponentThemes.appBarTheme(colorScheme),
|
|
filledButtonTheme: ComponentThemes.filledButtonTheme(colorScheme),
|
|
elevatedButtonTheme: ComponentThemes.elevatedButtonTheme(colorScheme),
|
|
outlinedButtonTheme: ComponentThemes.outlinedButtonTheme(colorScheme),
|
|
inputDecorationTheme: ComponentThemes.inputDecorationTheme(colorScheme),
|
|
snackBarTheme: ComponentThemes.snackBarTheme(colorScheme),
|
|
dialogTheme: ComponentThemes.dialogTheme(colorScheme),
|
|
bottomNavigationBarTheme:
|
|
ComponentThemes.bottomNavigationBarTheme(colorScheme),
|
|
chipTheme: ComponentThemes.chipTheme(colorScheme),
|
|
progressIndicatorTheme:
|
|
ComponentThemes.progressIndicatorTheme(colorScheme),
|
|
floatingActionButtonTheme:
|
|
ComponentThemes.floatingActionButtonTheme(colorScheme),
|
|
sliderTheme: ComponentThemes.sliderTheme(colorScheme),
|
|
);
|
|
}
|
|
}
|