feat(ui): add themed shell navigation
This commit is contained in:
184
lib/theme/app_theme.dart
Normal file
184
lib/theme/app_theme.dart
Normal file
@ -0,0 +1,184 @@
|
||||
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)),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user