118 lines
4.7 KiB
Dart
118 lines
4.7 KiB
Dart
import 'package:flutter/material.dart';
|
||
|
||
/// Light/dark [ThemeData] built from the forest-green palette in the
|
||
/// "Fuel Refund App" theme mockups (`themes_4.html`). Each scheme starts
|
||
/// from [ColorScheme.fromSeed] on the mockup's brand green — for full,
|
||
/// harmonious Material 3 role coverage (secondary/tertiary/error/etc.,
|
||
/// which the mockup doesn't specify) — then pins the roles the mockup
|
||
/// *does* specify (primary, surface tiers, text, outline) to its exact
|
||
/// values, so the dominant, most-visible colors match precisely.
|
||
class AppTheme {
|
||
AppTheme._();
|
||
|
||
// --- Light tokens (theme-light in themes_4.html) ---
|
||
static const _lightPrimary = Color(0xFF24603A); // --brand
|
||
static const _lightPrimaryInk = Color(0xFF1C5030); // --brand-ink
|
||
static const _lightSurface = Color(0xFFFFFFFF); // --screen / --surface
|
||
static const _lightSurfaceContainer = Color(0xFFF4F6F3); // --surface-2
|
||
static const _lightOnSurface = Color(0xFF14181A); // --text
|
||
static const _lightOnSurfaceVariant = Color(0xFF6A7377); // --text-2
|
||
static const _lightOutline = Color(0xFF8B9499); // --text-3
|
||
static const _lightOutlineVariant = Color(0xFFE9E9E4); // --line
|
||
|
||
// --- Dark tokens (theme-dark in themes_4.html) ---
|
||
static const _darkPrimary = Color(0xFF7BC47F); // --brand
|
||
static const _darkPrimaryInk = Color(0xFF9BD79E); // --brand-ink
|
||
static const _darkSurface = Color(0xFF101110); // --screen
|
||
static const _darkSurfaceContainer = Color(0xFF1A1C1A); // --surface
|
||
static const _darkSurfaceContainerHigh = Color(0xFF202320); // --surface-2
|
||
static const _darkOnSurface = Color(0xFFF2F4F1); // --text
|
||
static const _darkOnSurfaceVariant = Color(0xFF9AA39B); // --text-2
|
||
static const _darkOutline = Color(0xFF7E877F); // --text-3
|
||
static const _darkOutlineVariant = Color(0xFF262926); // --line
|
||
|
||
static ThemeData get light {
|
||
final colorScheme = ColorScheme.fromSeed(
|
||
seedColor: _lightPrimary,
|
||
brightness: Brightness.light,
|
||
).copyWith(
|
||
primary: _lightPrimary,
|
||
secondary: _lightPrimaryInk,
|
||
surface: _lightSurface,
|
||
surfaceContainerHighest: _lightSurfaceContainer,
|
||
onSurface: _lightOnSurface,
|
||
onSurfaceVariant: _lightOnSurfaceVariant,
|
||
outline: _lightOutline,
|
||
outlineVariant: _lightOutlineVariant,
|
||
);
|
||
return _themeFrom(colorScheme);
|
||
}
|
||
|
||
static ThemeData get dark {
|
||
final colorScheme = ColorScheme.fromSeed(
|
||
seedColor: _darkPrimary,
|
||
brightness: Brightness.dark,
|
||
).copyWith(
|
||
primary: _darkPrimary,
|
||
secondary: _darkPrimaryInk,
|
||
surface: _darkSurface,
|
||
surfaceContainer: _darkSurfaceContainer,
|
||
surfaceContainerHighest: _darkSurfaceContainerHigh,
|
||
onSurface: _darkOnSurface,
|
||
onSurfaceVariant: _darkOnSurfaceVariant,
|
||
outline: _darkOutline,
|
||
outlineVariant: _darkOutlineVariant,
|
||
);
|
||
return _themeFrom(colorScheme);
|
||
}
|
||
|
||
/// Component-level shaping shared by both brightnesses: the mockup's
|
||
/// rounded cards (14–15px), pill-shaped chips/badges, and hairline
|
||
/// dividers pulled from --line/--outlineVariant rather than Material's
|
||
/// default divider color.
|
||
static ThemeData _themeFrom(ColorScheme colorScheme) {
|
||
return ThemeData(
|
||
useMaterial3: true,
|
||
colorScheme: colorScheme,
|
||
scaffoldBackgroundColor: colorScheme.surface,
|
||
dividerTheme: DividerThemeData(color: colorScheme.outlineVariant, space: 1),
|
||
cardTheme: CardThemeData(
|
||
color: colorScheme.surfaceContainerHighest,
|
||
elevation: 0,
|
||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)),
|
||
),
|
||
chipTheme: ChipThemeData(
|
||
backgroundColor: colorScheme.primary.withValues(alpha: 0.10),
|
||
labelStyle: TextStyle(color: colorScheme.primary, fontWeight: FontWeight.w700),
|
||
shape: const StadiumBorder(),
|
||
side: BorderSide.none,
|
||
),
|
||
appBarTheme: AppBarTheme(
|
||
backgroundColor: colorScheme.surface,
|
||
foregroundColor: colorScheme.onSurface,
|
||
surfaceTintColor: Colors.transparent,
|
||
titleTextStyle: TextStyle(
|
||
color: colorScheme.onSurface,
|
||
fontSize: 18,
|
||
fontWeight: FontWeight.w700,
|
||
),
|
||
),
|
||
listTileTheme: ListTileThemeData(iconColor: colorScheme.onSurfaceVariant),
|
||
filledButtonTheme: FilledButtonThemeData(
|
||
style: FilledButton.styleFrom(
|
||
backgroundColor: colorScheme.primary,
|
||
foregroundColor: colorScheme.onPrimary,
|
||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||
),
|
||
),
|
||
inputDecorationTheme: InputDecorationTheme(
|
||
filled: true,
|
||
fillColor: colorScheme.surfaceContainerHighest,
|
||
border: OutlineInputBorder(
|
||
borderRadius: BorderRadius.circular(12),
|
||
borderSide: BorderSide.none,
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|