initial commit

This commit is contained in:
2026-07-27 14:42:23 +02:00
commit 833c68a189
257 changed files with 17947 additions and 0 deletions
+146
View File
@@ -0,0 +1,146 @@
import 'package:flutter/material.dart';
import 'app_colors.dart';
import 'app_data_styles.dart';
import 'status_colors.dart';
/// Builds the app's light/dark [ThemeData]. Colors are constructed
/// explicitly from [AppColors] rather than via [ColorScheme.fromSeed] so the
/// approved mockup's exact hex values can't drift through algorithmic tone
/// generation.
abstract final class AppTheme {
static ThemeData light() => _build(brightness: Brightness.light);
static ThemeData dark() => _build(brightness: Brightness.dark);
static ThemeData _build({required Brightness brightness}) {
final isDark = brightness == Brightness.dark;
final colorScheme = isDark
? const ColorScheme.dark(
surface: AppColors.darkBg,
onSurface: AppColors.darkText,
surfaceContainerHighest: AppColors.darkSurfaceAlt,
primary: AppColors.darkAccent,
onPrimary: AppColors.darkAccentInk,
secondary: AppColors.darkAccentStrong,
onSecondary: AppColors.darkAccentInk,
error: AppColors.critical,
onError: Colors.white,
outline: AppColors.darkBorder,
outlineVariant: AppColors.darkBorder,
)
: const ColorScheme.light(
surface: AppColors.lightBg,
onSurface: AppColors.lightText,
surfaceContainerHighest: AppColors.lightSurfaceAlt,
primary: AppColors.lightAccent,
onPrimary: AppColors.lightAccentInk,
secondary: AppColors.lightAccentStrong,
onSecondary: AppColors.lightAccentInk,
error: AppColors.critical,
onError: Colors.white,
outline: AppColors.lightBorder,
outlineVariant: AppColors.lightBorder,
);
final surfaceCard = isDark ? AppColors.darkSurface : AppColors.lightSurface;
final textColor = isDark ? AppColors.darkText : AppColors.lightText;
final textMuted = isDark ? AppColors.darkTextMuted : AppColors.lightTextMuted;
final textFaint = isDark ? AppColors.darkTextFaint : AppColors.lightTextFaint;
final border = isDark ? AppColors.darkBorder : AppColors.lightBorder;
final textTheme = TextTheme(
displaySmall: TextStyle(fontFamily: 'Inter', fontWeight: FontWeight.w700, fontSize: 30, color: textColor, letterSpacing: -0.2),
headlineSmall: TextStyle(fontFamily: 'Inter', fontWeight: FontWeight.w700, fontSize: 22, color: textColor, letterSpacing: -0.1),
titleLarge: TextStyle(fontFamily: 'Inter', fontWeight: FontWeight.w700, fontSize: 17, color: textColor, letterSpacing: -0.1),
titleMedium: TextStyle(fontFamily: 'Inter', fontWeight: FontWeight.w600, fontSize: 14, color: textColor),
titleSmall: TextStyle(fontFamily: 'Inter', fontWeight: FontWeight.w700, fontSize: 11, color: textFaint, letterSpacing: 0.6),
bodyLarge: TextStyle(fontFamily: 'Inter', fontWeight: FontWeight.w400, fontSize: 15, color: textColor, height: 1.5),
bodyMedium: TextStyle(fontFamily: 'Inter', fontWeight: FontWeight.w400, fontSize: 13.5, color: textColor, height: 1.45),
bodySmall: TextStyle(fontFamily: 'Inter', fontWeight: FontWeight.w500, fontSize: 12, color: textMuted),
labelLarge: TextStyle(fontFamily: 'Inter', fontWeight: FontWeight.w600, fontSize: 13, color: textColor),
labelMedium: TextStyle(fontFamily: 'Inter', fontWeight: FontWeight.w600, fontSize: 12, color: textMuted),
labelSmall: TextStyle(fontFamily: 'Inter', fontWeight: FontWeight.w700, fontSize: 11, color: textFaint, letterSpacing: 0.5),
);
return ThemeData(
useMaterial3: true,
brightness: brightness,
colorScheme: colorScheme,
scaffoldBackgroundColor: colorScheme.surface,
canvasColor: colorScheme.surface,
dividerColor: border,
fontFamily: 'Inter',
textTheme: textTheme,
cardTheme: CardThemeData(
color: surfaceCard,
elevation: 0,
margin: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
side: BorderSide(color: border),
),
),
appBarTheme: AppBarTheme(
backgroundColor: colorScheme.surface,
foregroundColor: textColor,
elevation: 0,
surfaceTintColor: Colors.transparent,
),
navigationRailTheme: NavigationRailThemeData(
backgroundColor: isDark ? AppColors.darkSurfaceAlt : AppColors.lightSurfaceAlt,
indicatorColor: colorScheme.primary.withValues(alpha: 0.16),
selectedIconTheme: IconThemeData(color: colorScheme.secondary),
unselectedIconTheme: IconThemeData(color: textMuted),
selectedLabelTextStyle: TextStyle(color: colorScheme.secondary, fontWeight: FontWeight.w700, fontSize: 12.5),
unselectedLabelTextStyle: TextStyle(color: textMuted, fontWeight: FontWeight.w500, fontSize: 12.5),
),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: colorScheme.primary,
foregroundColor: colorScheme.onPrimary,
elevation: 0,
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(7)),
textStyle: const TextStyle(fontFamily: 'Inter', fontWeight: FontWeight.w600, fontSize: 13),
),
),
outlinedButtonTheme: OutlinedButtonThemeData(
style: OutlinedButton.styleFrom(
foregroundColor: textColor,
side: BorderSide(color: border),
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(7)),
textStyle: const TextStyle(fontFamily: 'Inter', fontWeight: FontWeight.w600, fontSize: 13),
),
),
inputDecorationTheme: InputDecorationTheme(
filled: true,
fillColor: colorScheme.surface,
contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(7),
borderSide: BorderSide(color: border),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(7),
borderSide: BorderSide(color: border),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(7),
borderSide: BorderSide(color: colorScheme.primary, width: 1.5),
),
labelStyle: TextStyle(color: textMuted, fontSize: 12.5, fontWeight: FontWeight.w600),
),
dataTableTheme: DataTableThemeData(
headingTextStyle: TextStyle(fontFamily: 'Inter', fontWeight: FontWeight.w700, fontSize: 11, color: textFaint, letterSpacing: 0.5),
dataTextStyle: TextStyle(fontFamily: 'Inter', fontSize: 13, color: textColor),
dividerThickness: 1,
),
extensions: [
isDark ? StatusColors.dark : StatusColors.light,
AppDataStyles.resolve(textColor: textColor, mutedColor: textMuted),
],
);
}
}