import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../unionflow_design_system.dart'; /// AppBar standardisé UnionFlow /// /// Composant AppBar unifié pour toutes les pages de détail/formulaire. /// Garantit la cohérence visuelle et l'expérience utilisateur. /// /// ### Mode module (identité chromatique) /// /// Passez [moduleColor] ou [moduleGradient] pour afficher un AppBar avec /// le gradient signature du module, rappelant visuellement à l'utilisateur /// dans quelle section de l'application il se trouve. /// /// ```dart /// UFAppBar( /// title: 'Gestion des Organisations', /// moduleGradient: ModuleColors.organisationsGradient, /// ) /// ``` /// /// ### Mode standard /// /// Sans [moduleColor] ni [moduleGradient], le comportement existant est /// préservé intégralement (backgroundColor, foregroundColor, etc.). class UFAppBar extends StatelessWidget implements PreferredSizeWidget { final String title; final List? actions; final Widget? leading; final bool automaticallyImplyLeading; /// Fusionne le bouton retour et le titre en une seule zone (retour visible, /// même couleur que le titre). final bool mergeLeadingWithTitle; final PreferredSizeWidget? bottom; final Color? backgroundColor; final Color? foregroundColor; final double elevation; /// Couleur primaire du module — génère automatiquement un gradient subtil. /// Prend le dessus sur [backgroundColor] si renseigné. final Color? moduleColor; /// Gradient du module (liste de 2 couleurs) — ex: ModuleColors.organisationsGradient. /// Prend le dessus sur [moduleColor] et [backgroundColor] si renseigné. final List? moduleGradient; const UFAppBar({ super.key, required this.title, this.actions, this.leading, this.automaticallyImplyLeading = true, this.mergeLeadingWithTitle = false, this.bottom, this.backgroundColor, this.foregroundColor, this.elevation = 0, this.moduleColor, this.moduleGradient, }); bool get _isModuleMode => moduleGradient != null || moduleColor != null; List get _resolvedGradient { if (moduleGradient != null) return moduleGradient!; final c = moduleColor!; // Génère un gradient sombre → clair depuis la couleur du module final hsl = HSLColor.fromColor(c); final dark = hsl.withLightness((hsl.lightness - 0.06).clamp(0.0, 1.0)).toColor(); return [dark, c]; } @override Widget build(BuildContext context) { final canPop = ModalRoute.of(context)?.canPop ?? false; final fg = foregroundColor ?? Colors.white; final useMergedTitle = mergeLeadingWithTitle && canPop; final isTransparent = backgroundColor == Colors.transparent || (backgroundColor != null && backgroundColor!.opacity < 0.1); Widget titleWidget = useMergedTitle ? Row( children: [ Material( color: isTransparent ? Colors.black26 : Colors.transparent, borderRadius: BorderRadius.circular(20), child: IconButton( icon: const Icon(Icons.arrow_back), onPressed: () => Navigator.of(context).pop(), color: fg, tooltip: 'Retour', style: IconButton.styleFrom( foregroundColor: fg, ), ), ), const SizedBox(width: 8), Expanded( child: Text( title, style: AppTypography.headerSmall.copyWith( color: fg, fontWeight: FontWeight.w600, ), overflow: TextOverflow.ellipsis, ), ), ], ) : Text(title); // Mode module : gradient via flexibleSpace // iconTheme + actionsIconTheme explicites pour garantir la visibilité // des icônes sur fond gradient sombre (foregroundColor seul ne suffit pas // quand backgroundColor est transparent). if (_isModuleMode) { final gradient = _resolvedGradient; return AppBar( title: titleWidget, backgroundColor: Colors.transparent, foregroundColor: Colors.white, elevation: elevation, leading: useMergedTitle ? null : leading, automaticallyImplyLeading: useMergedTitle ? false : automaticallyImplyLeading, actions: actions, bottom: bottom, iconTheme: const IconThemeData(color: Colors.white, size: 22), actionsIconTheme: const IconThemeData(color: Colors.white, size: 22), systemOverlayStyle: const SystemUiOverlayStyle( statusBarColor: Colors.transparent, statusBarIconBrightness: Brightness.light, statusBarBrightness: Brightness.dark, ), centerTitle: false, titleTextStyle: AppTypography.headerSmall.copyWith( color: Colors.white, fontWeight: FontWeight.w600, ), flexibleSpace: Container( decoration: BoxDecoration( gradient: LinearGradient( colors: gradient, begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), ), ); } // Mode standard (comportement existant préservé) return AppBar( title: titleWidget, backgroundColor: backgroundColor ?? AppColors.primary, foregroundColor: fg, elevation: elevation, leading: useMergedTitle ? null : leading, automaticallyImplyLeading: useMergedTitle ? false : automaticallyImplyLeading, actions: actions, bottom: bottom, systemOverlayStyle: const SystemUiOverlayStyle( statusBarColor: Colors.transparent, statusBarIconBrightness: Brightness.light, statusBarBrightness: Brightness.dark, ), centerTitle: false, titleTextStyle: AppTypography.headerSmall.copyWith( color: fg, fontWeight: FontWeight.w600, ), ); } @override Size get preferredSize => Size.fromHeight( kToolbarHeight + (bottom?.preferredSize.height ?? 0.0), ); }