/// Thème Sophistiqué UnionFlow /// /// Implémentation complète du design system avec les dernières tendances UI/UX 2024-2025 /// Architecture modulaire et tokens de design cohérents library app_theme_sophisticated; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../tokens/color_tokens.dart'; import '../tokens/typography_tokens.dart'; import '../tokens/spacing_tokens.dart'; /// Thème principal de l'application UnionFlow class AppThemeSophisticated { AppThemeSophisticated._(); // ═══════════════════════════════════════════════════════════════════════════ // THÈME PRINCIPAL - Configuration complète // ═══════════════════════════════════════════════════════════════════════════ /// Thème clair principal static ThemeData get lightTheme { return ThemeData( useMaterial3: true, brightness: Brightness.light, // Couleurs principales colorScheme: _lightColorScheme, // Typographie textTheme: _textTheme, // Configuration de l'AppBar appBarTheme: _appBarTheme, // Configuration des cartes cardTheme: _cardTheme, // Configuration des boutons elevatedButtonTheme: _elevatedButtonTheme, filledButtonTheme: _filledButtonTheme, outlinedButtonTheme: _outlinedButtonTheme, textButtonTheme: _textButtonTheme, // Configuration des champs de saisie inputDecorationTheme: _inputDecorationTheme, // Configuration de la navigation navigationBarTheme: _navigationBarTheme, navigationDrawerTheme: _navigationDrawerTheme, // Configuration des dialogues dialogTheme: _dialogTheme, // Configuration des snackbars snackBarTheme: _snackBarTheme, // Configuration des puces chipTheme: _chipTheme, // Configuration des listes listTileTheme: _listTileTheme, // Configuration des onglets tabBarTheme: _tabBarTheme, // Configuration des dividers dividerTheme: _dividerTheme, // Configuration des icônes iconTheme: _iconTheme, // Configuration des surfaces scaffoldBackgroundColor: ColorTokens.surface, canvasColor: ColorTokens.surface, // Configuration des animations pageTransitionsTheme: _pageTransitionsTheme, // Configuration des extensions extensions: const [ _customColors, _customSpacing, ], ); } // ═══════════════════════════════════════════════════════════════════════════ // SCHÉMA DE COULEURS // ═══════════════════════════════════════════════════════════════════════════ static const ColorScheme _lightColorScheme = ColorScheme.light( // Couleurs primaires primary: ColorTokens.primary, onPrimary: ColorTokens.onPrimary, primaryContainer: ColorTokens.primaryContainer, onPrimaryContainer: ColorTokens.onPrimaryContainer, // Couleurs secondaires secondary: ColorTokens.secondary, onSecondary: ColorTokens.onSecondary, secondaryContainer: ColorTokens.secondaryContainer, onSecondaryContainer: ColorTokens.onSecondaryContainer, // Couleurs tertiaires tertiary: ColorTokens.tertiary, onTertiary: ColorTokens.onTertiary, tertiaryContainer: ColorTokens.tertiaryContainer, onTertiaryContainer: ColorTokens.onTertiaryContainer, // Couleurs d'erreur error: ColorTokens.error, onError: ColorTokens.onError, errorContainer: ColorTokens.errorContainer, onErrorContainer: ColorTokens.onErrorContainer, // Couleurs de surface surface: ColorTokens.surface, onSurface: ColorTokens.onSurface, surfaceContainerHighest: ColorTokens.surfaceVariant, onSurfaceVariant: ColorTokens.onSurfaceVariant, // Couleurs de contour outline: ColorTokens.outline, outlineVariant: ColorTokens.outlineVariant, // Couleurs d'ombre shadow: ColorTokens.shadow, scrim: ColorTokens.shadow, // Couleurs d'inversion inverseSurface: ColorTokens.onSurface, onInverseSurface: ColorTokens.surface, inversePrimary: ColorTokens.primaryLight, ); // ═══════════════════════════════════════════════════════════════════════════ // THÈME TYPOGRAPHIQUE // ═══════════════════════════════════════════════════════════════════════════ static const TextTheme _textTheme = TextTheme( // Display styles displayLarge: TypographyTokens.displayLarge, displayMedium: TypographyTokens.displayMedium, displaySmall: TypographyTokens.displaySmall, // Headline styles headlineLarge: TypographyTokens.headlineLarge, headlineMedium: TypographyTokens.headlineMedium, headlineSmall: TypographyTokens.headlineSmall, // Title styles titleLarge: TypographyTokens.titleLarge, titleMedium: TypographyTokens.titleMedium, titleSmall: TypographyTokens.titleSmall, // Label styles labelLarge: TypographyTokens.labelLarge, labelMedium: TypographyTokens.labelMedium, labelSmall: TypographyTokens.labelSmall, // Body styles bodyLarge: TypographyTokens.bodyLarge, bodyMedium: TypographyTokens.bodyMedium, bodySmall: TypographyTokens.bodySmall, ); // ═══════════════════════════════════════════════════════════════════════════ // THÈMES DE COMPOSANTS // ═══════════════════════════════════════════════════════════════════════════ /// Configuration AppBar moderne (sans AppBar traditionnelle) static const AppBarTheme _appBarTheme = AppBarTheme( elevation: 0, scrolledUnderElevation: 0, backgroundColor: Colors.transparent, foregroundColor: ColorTokens.onSurface, surfaceTintColor: Colors.transparent, systemOverlayStyle: SystemUiOverlayStyle( statusBarColor: Colors.transparent, statusBarIconBrightness: Brightness.dark, statusBarBrightness: Brightness.light, ), ); /// Configuration des cartes sophistiquées static final CardTheme _cardTheme = CardTheme( elevation: SpacingTokens.elevationSm, shadowColor: ColorTokens.shadow, surfaceTintColor: ColorTokens.surfaceContainer, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(SpacingTokens.radiusLg), ), margin: const EdgeInsets.all(SpacingTokens.cardMargin), ); /// Configuration des boutons élevés static final ElevatedButtonThemeData _elevatedButtonTheme = ElevatedButtonThemeData( style: ElevatedButton.styleFrom( elevation: SpacingTokens.elevationSm, shadowColor: ColorTokens.shadow, backgroundColor: ColorTokens.primary, foregroundColor: ColorTokens.onPrimary, textStyle: TypographyTokens.buttonMedium, padding: const EdgeInsets.symmetric( horizontal: SpacingTokens.buttonPaddingHorizontal, vertical: SpacingTokens.buttonPaddingVertical, ), minimumSize: const Size( SpacingTokens.minButtonWidth, SpacingTokens.buttonHeightMedium, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(SpacingTokens.radiusMd), ), ), ); /// Configuration des boutons remplis static final FilledButtonThemeData _filledButtonTheme = FilledButtonThemeData( style: FilledButton.styleFrom( backgroundColor: ColorTokens.primary, foregroundColor: ColorTokens.onPrimary, textStyle: TypographyTokens.buttonMedium, padding: const EdgeInsets.symmetric( horizontal: SpacingTokens.buttonPaddingHorizontal, vertical: SpacingTokens.buttonPaddingVertical, ), minimumSize: const Size( SpacingTokens.minButtonWidth, SpacingTokens.buttonHeightMedium, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(SpacingTokens.radiusMd), ), ), ); /// Configuration des boutons avec contour static final OutlinedButtonThemeData _outlinedButtonTheme = OutlinedButtonThemeData( style: OutlinedButton.styleFrom( foregroundColor: ColorTokens.primary, textStyle: TypographyTokens.buttonMedium, padding: const EdgeInsets.symmetric( horizontal: SpacingTokens.buttonPaddingHorizontal, vertical: SpacingTokens.buttonPaddingVertical, ), minimumSize: const Size( SpacingTokens.minButtonWidth, SpacingTokens.buttonHeightMedium, ), side: const BorderSide( color: ColorTokens.outline, width: 1.0, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(SpacingTokens.radiusMd), ), ), ); /// Configuration des boutons texte static final TextButtonThemeData _textButtonTheme = TextButtonThemeData( style: TextButton.styleFrom( foregroundColor: ColorTokens.primary, textStyle: TypographyTokens.buttonMedium, padding: const EdgeInsets.symmetric( horizontal: SpacingTokens.buttonPaddingHorizontal, vertical: SpacingTokens.buttonPaddingVertical, ), minimumSize: const Size( SpacingTokens.minButtonWidth, SpacingTokens.buttonHeightMedium, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(SpacingTokens.radiusMd), ), ), ); /// Configuration des champs de saisie static final InputDecorationTheme _inputDecorationTheme = InputDecorationTheme( filled: true, fillColor: ColorTokens.surfaceContainer, labelStyle: TypographyTokens.inputLabel, hintStyle: TypographyTokens.inputHint, border: OutlineInputBorder( borderRadius: BorderRadius.circular(SpacingTokens.radiusMd), borderSide: const BorderSide(color: ColorTokens.outline), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(SpacingTokens.radiusMd), borderSide: const BorderSide(color: ColorTokens.outline), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(SpacingTokens.radiusMd), borderSide: const BorderSide(color: ColorTokens.primary, width: 2.0), ), errorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(SpacingTokens.radiusMd), borderSide: const BorderSide(color: ColorTokens.error), ), contentPadding: const EdgeInsets.all(SpacingTokens.formPadding), ); /// Configuration de la barre de navigation static final NavigationBarThemeData _navigationBarTheme = NavigationBarThemeData( backgroundColor: ColorTokens.navigationBackground, indicatorColor: ColorTokens.navigationIndicator, labelTextStyle: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.selected)) { return TypographyTokens.navigationLabelSelected; } return TypographyTokens.navigationLabel; }), iconTheme: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.selected)) { return const IconThemeData(color: ColorTokens.navigationSelected); } return const IconThemeData(color: ColorTokens.navigationUnselected); }), ); /// Configuration du drawer de navigation static final NavigationDrawerThemeData _navigationDrawerTheme = NavigationDrawerThemeData( backgroundColor: ColorTokens.surfaceContainer, elevation: SpacingTokens.elevationMd, shadowColor: ColorTokens.shadow, surfaceTintColor: ColorTokens.surfaceContainer, indicatorColor: ColorTokens.primaryContainer, labelTextStyle: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.selected)) { return TypographyTokens.navigationLabelSelected; } return TypographyTokens.navigationLabel; }), ); /// Configuration des dialogues static final DialogTheme _dialogTheme = DialogTheme( backgroundColor: ColorTokens.surfaceContainer, elevation: SpacingTokens.elevationLg, shadowColor: ColorTokens.shadow, surfaceTintColor: ColorTokens.surfaceContainer, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(SpacingTokens.radiusXl), ), titleTextStyle: TypographyTokens.headlineSmall, contentTextStyle: TypographyTokens.bodyMedium, ); /// Configuration des snackbars static final SnackBarThemeData _snackBarTheme = SnackBarThemeData( backgroundColor: ColorTokens.onSurface, contentTextStyle: TypographyTokens.bodyMedium.copyWith( color: ColorTokens.surface, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(SpacingTokens.radiusMd), ), behavior: SnackBarBehavior.floating, ); /// Configuration des puces static final ChipThemeData _chipTheme = ChipThemeData( backgroundColor: ColorTokens.surfaceVariant, selectedColor: ColorTokens.primaryContainer, labelStyle: TypographyTokens.labelMedium, padding: const EdgeInsets.symmetric( horizontal: SpacingTokens.md, vertical: SpacingTokens.sm, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(SpacingTokens.radiusMd), ), ); /// Configuration des éléments de liste static const ListTileThemeData _listTileTheme = ListTileThemeData( contentPadding: EdgeInsets.symmetric( horizontal: SpacingTokens.xl, vertical: SpacingTokens.md, ), titleTextStyle: TypographyTokens.titleMedium, subtitleTextStyle: TypographyTokens.bodyMedium, leadingAndTrailingTextStyle: TypographyTokens.labelMedium, minVerticalPadding: SpacingTokens.md, ); /// Configuration des onglets static final TabBarTheme _tabBarTheme = TabBarTheme( labelColor: ColorTokens.primary, unselectedLabelColor: ColorTokens.onSurfaceVariant, labelStyle: TypographyTokens.titleSmall, unselectedLabelStyle: TypographyTokens.titleSmall, indicator: UnderlineTabIndicator( borderSide: const BorderSide( color: ColorTokens.primary, width: 2.0, ), borderRadius: BorderRadius.circular(SpacingTokens.radiusXs), ), ); /// Configuration des dividers static const DividerThemeData _dividerTheme = DividerThemeData( color: ColorTokens.outline, thickness: 1.0, space: SpacingTokens.md, ); /// Configuration des icônes static const IconThemeData _iconTheme = IconThemeData( color: ColorTokens.onSurfaceVariant, size: 24.0, ); /// Configuration des transitions de page static const PageTransitionsTheme _pageTransitionsTheme = PageTransitionsTheme( builders: { TargetPlatform.android: CupertinoPageTransitionsBuilder(), TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), }, ); /// Extensions personnalisées - Couleurs static const CustomColors _customColors = CustomColors(); /// Extensions personnalisées - Espacements static const CustomSpacing _customSpacing = CustomSpacing(); } /// Extension de couleurs personnalisées class CustomColors extends ThemeExtension { const CustomColors(); @override CustomColors copyWith() => const CustomColors(); @override CustomColors lerp(ThemeExtension? other, double t) { return const CustomColors(); } } /// Extension d'espacements personnalisés class CustomSpacing extends ThemeExtension { const CustomSpacing(); @override CustomSpacing copyWith() => const CustomSpacing(); @override CustomSpacing lerp(ThemeExtension? other, double t) { return const CustomSpacing(); } }