import 'package:flutter/material.dart'; import '../../core/theme/app_color_scheme.dart'; import '../../core/theme/app_spacing.dart'; import '../../core/theme/app_theme_extension.dart'; /// NeonGlow - 霓虹光效組件 /// /// Material Design 3 風格的霓虹光效 /// 用於按鈕、卡片、圖標等需要突出顯示的元素 /// /// 光效類型: /// - Primary: 青色光效 (#72dcff) /// - Secondary: 紫色光效 (#dd8bfb) /// - Tertiary: 綠色光效 (#afffd1) /// - Error: 紅色光效 (#ff716c) class NeonGlow extends StatelessWidget { /// 子組件 final Widget child; /// 光效顏色 final Color glowColor; /// 模糊半徑,默認 15.0 final double blurRadius; /// 擴散半徑,默認 0.0 final double spreadRadius; /// 圓角 final BorderRadius? borderRadius; const NeonGlow({ super.key, required this.child, required this.glowColor, this.blurRadius = 15.0, this.spreadRadius = 0.0, this.borderRadius, }); /// Primary 霓虹光效 (青色) factory NeonGlow.primary({ Key? key, required Widget child, double blurRadius = 15.0, BorderRadius? borderRadius, }) { return NeonGlow( key: key, glowColor: AppColorScheme.neonGlowPrimary, blurRadius: blurRadius, borderRadius: borderRadius, child: child, ); } /// Secondary 霓虹光效 (紫色) factory NeonGlow.secondary({ Key? key, required Widget child, double blurRadius = 15.0, BorderRadius? borderRadius, }) { return NeonGlow( key: key, glowColor: AppColorScheme.neonGlowSecondary, blurRadius: blurRadius, borderRadius: borderRadius, child: child, ); } /// Tertiary 霓虹光效 (綠色) factory NeonGlow.tertiary({ Key? key, required Widget child, double blurRadius = 20.0, BorderRadius? borderRadius, }) { return NeonGlow( key: key, glowColor: AppColorScheme.neonGlowTertiary, blurRadius: blurRadius, borderRadius: borderRadius, child: child, ); } /// Error 霓虹光效 (紅色) factory NeonGlow.error({ Key? key, required Widget child, double blurRadius = 15.0, BorderRadius? borderRadius, }) { return NeonGlow( key: key, glowColor: AppColorScheme.down.withValues(alpha: 0.3), blurRadius: blurRadius, borderRadius: borderRadius, child: child, ); } @override Widget build(BuildContext context) { final br = borderRadius ?? BorderRadius.circular(AppRadius.xl); return Container( decoration: BoxDecoration( borderRadius: br, boxShadow: [ BoxShadow( color: glowColor, blurRadius: blurRadius, spreadRadius: spreadRadius, ), ], ), child: child, ); } } /// NeonButton - 帶霓虹光效的按鈕 /// /// 預設了常用配置,簡化使用 class NeonButton extends StatefulWidget { /// 按鈕文本 final String text; /// 點擊回調 final VoidCallback? onPressed; /// 按鈕類型 final NeonButtonType type; /// 是否顯示光效 final bool showGlow; /// 圖標 final IconData? icon; /// 是否加載中 final bool isLoading; /// 按鈕寬度 final double? width; /// 按鈕高度,默認 48 final double height; const NeonButton({ super.key, required this.text, this.onPressed, this.type = NeonButtonType.primary, this.showGlow = true, this.icon, this.isLoading = false, this.width, this.height = 48, }); @override State createState() => _NeonButtonState(); } class _NeonButtonState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _scaleAnimation; bool _isPressed = false; @override void initState() { super.initState(); _controller = AnimationController( duration: const Duration(milliseconds: 150), vsync: this, ); _scaleAnimation = Tween(begin: 1.0, end: 0.95).animate( CurvedAnimation(parent: _controller, curve: Curves.easeInOut), ); } @override void dispose() { _controller.dispose(); super.dispose(); } void _onTapDown(TapDownDetails details) { setState(() => _isPressed = true); _controller.forward(); } void _onTapUp(TapUpDetails details) { setState(() => _isPressed = false); _controller.reverse(); } void _onTapCancel() { setState(() => _isPressed = false); _controller.reverse(); } Color get _backgroundColor { final colors = context.colors; switch (widget.type) { case NeonButtonType.primary: return colors.primary; case NeonButtonType.secondary: return colors.secondary; case NeonButtonType.tertiary: return context.appColors.up; case NeonButtonType.error: return AppColorScheme.down; case NeonButtonType.outline: return Colors.transparent; } } Color get _foregroundColor { final colors = context.colors; switch (widget.type) { case NeonButtonType.primary: return colors.onPrimary; case NeonButtonType.secondary: return colors.onSecondary; case NeonButtonType.tertiary: return colors.onTertiary; case NeonButtonType.error: return const Color(0xFFFFFFFF); case NeonButtonType.outline: return colors.primary; } } Color get _glowColor { final colors = context.colors; final appColors = context.appColors; switch (widget.type) { case NeonButtonType.primary: return colors.primary.withValues(alpha: appColors.glowOpacity); case NeonButtonType.secondary: return colors.secondary.withValues(alpha: appColors.glowOpacity); case NeonButtonType.tertiary: return context.appColors.upBackground; case NeonButtonType.error: return AppColorScheme.down.withValues(alpha: 0.3); case NeonButtonType.outline: return colors.primary.withValues(alpha: appColors.glowOpacity); } } LinearGradient? get _gradient { // 【優化】移除所有漸變效果,改為純色背景,提升專業金融感 return null; } @override Widget build(BuildContext context) { final colors = context.colors; final button = GestureDetector( onTapDown: widget.onPressed != null ? _onTapDown : null, onTapUp: widget.onPressed != null ? _onTapUp : null, onTapCancel: widget.onPressed != null ? _onTapCancel : null, onTap: widget.isLoading ? null : widget.onPressed, child: ScaleTransition( scale: _scaleAnimation, child: Container( width: widget.width, height: widget.height, decoration: BoxDecoration( gradient: _gradient, color: _gradient == null ? _backgroundColor : null, borderRadius: BorderRadius.circular( widget.type == NeonButtonType.outline ? AppRadius.md : AppRadius.lg, ), border: widget.type == NeonButtonType.outline ? Border.all( color: colors.outlineVariant.withValues(alpha: 0.3), ) : null, ), child: Center( child: widget.isLoading ? SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(_foregroundColor), ), ) : Row( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ if (widget.icon != null) ...[ Icon(widget.icon, size: 18, color: _foregroundColor), SizedBox(width: AppSpacing.sm), ], Text( widget.text, style: TextStyle( color: _foregroundColor, fontSize: 16, fontWeight: FontWeight.w600, ), ), ], ), ), ), ), ); if (widget.showGlow && widget.type != NeonButtonType.outline) { return NeonGlow( glowColor: _glowColor, borderRadius: BorderRadius.circular( widget.type == NeonButtonType.outline ? AppRadius.md : AppRadius.lg, ), child: button, ); } return button; } } /// 按鈕類型 enum NeonButtonType { /// 主要按鈕 (青色) primary, /// 次要按鈕 (紫色) secondary, /// 成功按鈕 (綠色) tertiary, /// 危險按鈕 (紅色) error, /// 邊框按鈕 outline, } /// NeonIcon - 帶霓虹光效的圖標 class NeonIcon extends StatelessWidget { /// 圖標 final IconData icon; /// 圖標大小 final double size; /// 圖標顏色 final Color color; /// 光效顏色,默認使用圖標顏色 final Color? glowColor; /// 光效模糊半徑 final double glowBlur; const NeonIcon({ super.key, required this.icon, this.size = 24, required this.color, this.glowColor, this.glowBlur = 10, }); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( boxShadow: [ BoxShadow( color: glowColor ?? color.withValues(alpha: 0.5), blurRadius: glowBlur, spreadRadius: 0, ), ], ), child: Icon(icon, size: size, color: color), ); } }