185 lines
6.3 KiB
Dart
185 lines
6.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
class AppTheme {
|
|
static const Color brandBlue = Color(0xFF2F7BFF);
|
|
static const Color darkBackground = Color(0xFF071A2E);
|
|
static const Color darkSurface = Color(0xFF10253A);
|
|
static const Color darkSurfaceAlt = Color(0xFF173149);
|
|
static const Color lightBackground = Color(0xFFF4F8FC);
|
|
static const Color lightSurface = Color(0xFFFFFFFF);
|
|
static const Color lightSurfaceAlt = Color(0xFFEAF1F8);
|
|
|
|
static ThemeData light() {
|
|
return _buildTheme(
|
|
brightness: Brightness.light,
|
|
colorScheme: ColorScheme.fromSeed(
|
|
seedColor: brandBlue,
|
|
brightness: Brightness.light,
|
|
primary: brandBlue,
|
|
surface: lightSurface,
|
|
),
|
|
scaffoldBackgroundColor: lightBackground,
|
|
panelColor: lightSurface,
|
|
panelAltColor: lightSurfaceAlt,
|
|
);
|
|
}
|
|
|
|
static ThemeData dark() {
|
|
return _buildTheme(
|
|
brightness: Brightness.dark,
|
|
colorScheme: ColorScheme.fromSeed(
|
|
seedColor: brandBlue,
|
|
brightness: Brightness.dark,
|
|
primary: brandBlue,
|
|
surface: darkSurface,
|
|
),
|
|
scaffoldBackgroundColor: darkBackground,
|
|
panelColor: darkSurface,
|
|
panelAltColor: darkSurfaceAlt,
|
|
);
|
|
}
|
|
|
|
static ThemeData _buildTheme({
|
|
required Brightness brightness,
|
|
required ColorScheme colorScheme,
|
|
required Color scaffoldBackgroundColor,
|
|
required Color panelColor,
|
|
required Color panelAltColor,
|
|
}) {
|
|
final isDark = brightness == Brightness.dark;
|
|
final onSurfaceMuted = colorScheme.onSurface.withValues(alpha: 0.68);
|
|
final baseChipTheme = ThemeData(
|
|
useMaterial3: true,
|
|
brightness: brightness,
|
|
colorScheme: colorScheme,
|
|
).chipTheme;
|
|
|
|
return ThemeData(
|
|
useMaterial3: true,
|
|
brightness: brightness,
|
|
colorScheme: colorScheme,
|
|
scaffoldBackgroundColor: scaffoldBackgroundColor,
|
|
dividerColor: colorScheme.outlineVariant.withValues(alpha: 0.42),
|
|
appBarTheme: AppBarTheme(
|
|
elevation: 0,
|
|
scrolledUnderElevation: 0,
|
|
backgroundColor: Colors.transparent,
|
|
foregroundColor: colorScheme.onSurface,
|
|
centerTitle: false,
|
|
titleTextStyle: TextStyle(
|
|
color: colorScheme.onSurface,
|
|
fontSize: 28,
|
|
fontWeight: FontWeight.w700,
|
|
letterSpacing: -0.5,
|
|
),
|
|
),
|
|
cardTheme: CardThemeData(
|
|
elevation: 0,
|
|
color: panelColor,
|
|
margin: EdgeInsets.zero,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(22),
|
|
side: BorderSide(
|
|
color: colorScheme.outlineVariant.withValues(alpha: 0.55),
|
|
),
|
|
),
|
|
),
|
|
navigationBarTheme: NavigationBarThemeData(
|
|
backgroundColor: panelColor,
|
|
indicatorColor: colorScheme.primary.withValues(alpha: isDark ? 0.20 : 0.14),
|
|
labelTextStyle: WidgetStateProperty.resolveWith(
|
|
(states) => TextStyle(
|
|
fontSize: 12,
|
|
fontWeight: states.contains(WidgetState.selected)
|
|
? FontWeight.w700
|
|
: FontWeight.w500,
|
|
),
|
|
),
|
|
),
|
|
filledButtonTheme: FilledButtonThemeData(
|
|
style: FilledButton.styleFrom(
|
|
backgroundColor: colorScheme.primary,
|
|
foregroundColor: colorScheme.onPrimary,
|
|
minimumSize: const Size.fromHeight(52),
|
|
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 14),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(16),
|
|
),
|
|
textStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w700),
|
|
),
|
|
),
|
|
outlinedButtonTheme: OutlinedButtonThemeData(
|
|
style: OutlinedButton.styleFrom(
|
|
foregroundColor: colorScheme.onSurface,
|
|
minimumSize: const Size.fromHeight(48),
|
|
side: BorderSide(
|
|
color: colorScheme.outlineVariant.withValues(alpha: 0.8),
|
|
),
|
|
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 14),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(16),
|
|
),
|
|
),
|
|
),
|
|
textButtonTheme: TextButtonThemeData(
|
|
style: TextButton.styleFrom(
|
|
foregroundColor: colorScheme.primary,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(14),
|
|
),
|
|
),
|
|
),
|
|
listTileTheme: ListTileThemeData(
|
|
iconColor: colorScheme.primary,
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(18)),
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
),
|
|
chipTheme: baseChipTheme.copyWith(
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(999),
|
|
),
|
|
side: BorderSide(
|
|
color: colorScheme.outlineVariant.withValues(alpha: 0.6),
|
|
),
|
|
),
|
|
inputDecorationTheme: InputDecorationTheme(
|
|
filled: true,
|
|
fillColor: panelAltColor,
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
|
|
hintStyle: TextStyle(color: onSurfaceMuted),
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(16),
|
|
borderSide: BorderSide.none,
|
|
),
|
|
enabledBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(16),
|
|
borderSide: BorderSide(
|
|
color: colorScheme.outlineVariant.withValues(alpha: 0.55),
|
|
),
|
|
),
|
|
focusedBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(16),
|
|
borderSide: BorderSide(color: colorScheme.primary, width: 1.2),
|
|
),
|
|
),
|
|
dialogTheme: DialogThemeData(
|
|
backgroundColor: panelColor,
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)),
|
|
),
|
|
bottomSheetTheme: BottomSheetThemeData(
|
|
backgroundColor: panelColor,
|
|
modalBackgroundColor: panelColor,
|
|
shape: const RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(28)),
|
|
),
|
|
),
|
|
snackBarTheme: SnackBarThemeData(
|
|
behavior: SnackBarBehavior.floating,
|
|
backgroundColor: panelAltColor,
|
|
contentTextStyle: TextStyle(color: colorScheme.onSurface),
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
|
),
|
|
);
|
|
}
|
|
}
|