Files
unionflow-server-api/unionflow-mobile-apps/lib/shared/design_system/components/uf_header.dart
2025-11-17 16:02:04 +00:00

128 lines
3.7 KiB
Dart

import 'package:flutter/material.dart';
import '../unionflow_design_system.dart';
/// Header harmonisé UnionFlow
///
/// Composant header standardisé pour toutes les pages de l'application.
/// Garantit la cohérence visuelle et l'expérience utilisateur.
class UFHeader extends StatelessWidget {
final String title;
final String? subtitle;
final IconData icon;
final List<Widget>? actions;
final VoidCallback? onNotificationTap;
final VoidCallback? onSettingsTap;
final bool showActions;
const UFHeader({
super.key,
required this.title,
this.subtitle,
required this.icon,
this.actions,
this.onNotificationTap,
this.onSettingsTap,
this.showActions = true,
});
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(SpacingTokens.xl),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: ColorTokens.primaryGradient,
),
borderRadius: BorderRadius.circular(SpacingTokens.radiusLg),
boxShadow: ShadowTokens.primary,
),
child: Row(
children: [
// Icône et contenu principal
Container(
padding: const EdgeInsets.all(SpacingTokens.sm),
decoration: BoxDecoration(
color: ColorTokens.onPrimary.withOpacity(0.2),
borderRadius: BorderRadius.circular(SpacingTokens.radiusMd),
),
child: Icon(
icon,
color: ColorTokens.onPrimary,
size: 24,
),
),
const SizedBox(width: SpacingTokens.lg),
// Titre et sous-titre
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: TypographyTokens.titleLarge.copyWith(
color: ColorTokens.onPrimary,
),
),
if (subtitle != null) ...[
const SizedBox(height: SpacingTokens.xs),
Text(
subtitle!,
style: TypographyTokens.bodySmall.copyWith(
color: ColorTokens.onPrimary.withOpacity(0.8),
),
),
],
],
),
),
// Actions
if (showActions) _buildActions(),
],
),
);
}
Widget _buildActions() {
if (actions != null) {
return Row(children: actions!);
}
return Row(
children: [
if (onNotificationTap != null)
Container(
decoration: BoxDecoration(
color: ColorTokens.onPrimary.withOpacity(0.2),
borderRadius: BorderRadius.circular(SpacingTokens.radiusSm),
),
child: IconButton(
onPressed: onNotificationTap,
icon: const Icon(
Icons.notifications_outlined,
color: ColorTokens.onPrimary,
),
),
),
if (onNotificationTap != null && onSettingsTap != null)
const SizedBox(width: SpacingTokens.sm),
if (onSettingsTap != null)
Container(
decoration: BoxDecoration(
color: ColorTokens.onPrimary.withOpacity(0.2),
borderRadius: BorderRadius.circular(SpacingTokens.radiusSm),
),
child: IconButton(
onPressed: onSettingsTap,
icon: const Icon(
Icons.settings_outlined,
color: ColorTokens.onPrimary,
),
),
),
],
);
}
}