/// UnionFlow Primary Button - Bouton principal /// /// Bouton primaire Vert Forêt (#2E7D32) /// Utilisé pour les actions principales (connexion, enregistrer, valider, etc.) library uf_primary_button; import 'package:flutter/material.dart'; import '../../unionflow_design_system.dart'; /// Bouton primaire UnionFlow /// /// Usage: /// ```dart /// UFPrimaryButton( /// label: 'Connexion', /// onPressed: () => login(), /// icon: Icons.login, /// isLoading: false, /// ) /// ``` class UFPrimaryButton extends StatelessWidget { /// Texte du bouton final String label; /// Callback appelé lors du clic final VoidCallback? onPressed; /// Indique si le bouton est en chargement final bool isLoading; /// Icône optionnelle à gauche du texte final IconData? icon; /// Bouton pleine largeur final bool isFullWidth; /// Hauteur personnalisée (optionnel) final double? height; /// Couleur de fond personnalisée (optionnel) final Color? backgroundColor; /// Couleur du texte/icône personnalisée (optionnel) final Color? textColor; const UFPrimaryButton({ super.key, required this.label, this.onPressed, this.isLoading = false, this.icon, this.isFullWidth = false, this.height, this.backgroundColor, this.textColor, }); @override Widget build(BuildContext context) { return SizedBox( width: isFullWidth ? double.infinity : null, height: height ?? SpacingTokens.buttonHeightMedium, child: ElevatedButton( onPressed: isLoading ? null : onPressed, style: ElevatedButton.styleFrom( backgroundColor: backgroundColor ?? AppColors.primary, foregroundColor: textColor ?? Colors.white, disabledBackgroundColor: (backgroundColor ?? AppColors.primary).withOpacity(0.5), disabledForegroundColor: (textColor ?? Colors.white).withOpacity(0.7), elevation: SpacingTokens.elevationSm, shadowColor: AppColors.borderDark.withOpacity(0.1), padding: const EdgeInsets.symmetric( horizontal: SpacingTokens.buttonPaddingHorizontal, vertical: 10, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(SpacingTokens.radiusMd), ), ), child: isLoading ? const SizedBox( height: 20, width: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( Colors.white, ), ), ) : Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ if (icon != null) ...[ Icon(icon, size: 20), const SizedBox(width: SpacingTokens.md), ], Text( label, style: AppTypography.actionText, ), ], ), ), ); } }