import 'package:flutter/material.dart'; import '../../app/theme/app_colors.dart'; import '../../app/theme/app_typography.dart'; import '../../app/theme/app_spacing.dart'; /// Genex 按钮组件 /// /// 统一的按钮样式,支持 primary/secondary/outline/text 4种变体 class GenexButton extends StatelessWidget { final String label; final VoidCallback? onPressed; final GenexButtonVariant variant; final GenexButtonSize size; final IconData? icon; final bool isLoading; final bool fullWidth; const GenexButton({ super.key, required this.label, this.onPressed, this.variant = GenexButtonVariant.primary, this.size = GenexButtonSize.large, this.icon, this.isLoading = false, this.fullWidth = true, }); @override Widget build(BuildContext context) { final child = Row( mainAxisSize: fullWidth ? MainAxisSize.max : MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ if (isLoading) ...[ SizedBox( width: 18, height: 18, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(_foregroundColor), ), ), const SizedBox(width: 8), ], if (icon != null && !isLoading) ...[ Icon(icon, size: 20), const SizedBox(width: 6), ], Text(label), ], ); final effectiveOnPressed = isLoading ? null : onPressed; switch (variant) { case GenexButtonVariant.primary: return SizedBox( width: fullWidth ? double.infinity : null, height: _height, child: ElevatedButton( onPressed: effectiveOnPressed, style: ElevatedButton.styleFrom( backgroundColor: AppColors.primary, foregroundColor: Colors.white, disabledBackgroundColor: AppColors.primary.withValues(alpha: 0.4), disabledForegroundColor: Colors.white70, elevation: 0, shape: RoundedRectangleBorder( borderRadius: AppSpacing.borderRadiusMd, ), textStyle: _textStyle, ), child: child, ), ); case GenexButtonVariant.secondary: return SizedBox( width: fullWidth ? double.infinity : null, height: _height, child: ElevatedButton( onPressed: effectiveOnPressed, style: ElevatedButton.styleFrom( backgroundColor: AppColors.primarySurface, foregroundColor: AppColors.primary, elevation: 0, shape: RoundedRectangleBorder( borderRadius: AppSpacing.borderRadiusMd, ), textStyle: _textStyle, ), child: child, ), ); case GenexButtonVariant.outline: return SizedBox( width: fullWidth ? double.infinity : null, height: _height, child: OutlinedButton( onPressed: effectiveOnPressed, style: OutlinedButton.styleFrom( foregroundColor: AppColors.primary, side: const BorderSide(color: AppColors.primary, width: 1.5), shape: RoundedRectangleBorder( borderRadius: AppSpacing.borderRadiusMd, ), textStyle: _textStyle, ), child: child, ), ); case GenexButtonVariant.text: return SizedBox( height: _height, child: TextButton( onPressed: effectiveOnPressed, style: TextButton.styleFrom( foregroundColor: AppColors.primary, textStyle: _textStyle, ), child: child, ), ); } } double get _height { switch (size) { case GenexButtonSize.large: return AppSpacing.buttonHeight; case GenexButtonSize.medium: return AppSpacing.buttonHeightSm; case GenexButtonSize.small: return 32; } } TextStyle get _textStyle { switch (size) { case GenexButtonSize.large: return AppTypography.labelLarge; case GenexButtonSize.medium: return AppTypography.labelMedium; case GenexButtonSize.small: return AppTypography.labelSmall; } } Color get _foregroundColor { switch (variant) { case GenexButtonVariant.primary: return Colors.white; default: return AppColors.primary; } } } enum GenexButtonVariant { primary, secondary, outline, text } enum GenexButtonSize { large, medium, small }