Files
submanager/lib/widgets/common/buttons/primary_button.dart
JiWoong Sul 2f60ef585a feat: 글래스모피즘 디자인 시스템 및 색상 가이드 전면 적용
- @doc/color.md 가이드라인에 따른 색상 시스템 전면 개편
- 딥 블루(#2563EB), 스카이 블루(#60A5FA) 메인 컬러로 변경
- 모든 화면과 위젯에 글래스모피즘 효과 일관성 있게 적용
- darkNavy, navyGray 등 새로운 텍스트 색상 체계 도입
- 공통 스낵바 및 다이얼로그 컴포넌트 추가
- Claude AI 프로젝트 컨텍스트 파일(CLAUDE.md) 추가

영향받은 컴포넌트:
- 10개 스크린 (main, settings, detail, splash 등)
- 30개 이상 위젯 (buttons, cards, forms 등)
- 테마 시스템 (AppColors, AppTheme)

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-11 18:41:05 +09:00

113 lines
3.5 KiB
Dart

import 'package:flutter/material.dart';
import '../../../theme/app_colors.dart';
/// 주요 액션에 사용되는 Primary 버튼
/// 저장, 추가, 확인 등의 주요 액션에 사용됩니다.
class PrimaryButton extends StatefulWidget {
final String text;
final VoidCallback? onPressed;
final bool isLoading;
final IconData? icon;
final double? width;
final double height;
final Color? backgroundColor;
final Color? foregroundColor;
final double fontSize;
final EdgeInsetsGeometry? padding;
final double borderRadius;
final bool enableHoverEffect;
const PrimaryButton({
super.key,
required this.text,
this.onPressed,
this.isLoading = false,
this.icon,
this.width,
this.height = 60,
this.backgroundColor,
this.foregroundColor,
this.fontSize = 18,
this.padding,
this.borderRadius = 16,
this.enableHoverEffect = true,
});
@override
State<PrimaryButton> createState() => _PrimaryButtonState();
}
class _PrimaryButtonState extends State<PrimaryButton> {
bool _isHovered = false;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final effectiveBackgroundColor = widget.backgroundColor ?? theme.primaryColor;
final effectiveForegroundColor = widget.foregroundColor ?? AppColors.pureWhite;
Widget button = AnimatedContainer(
duration: const Duration(milliseconds: 200),
width: widget.width ?? double.infinity,
height: widget.height,
transform: widget.enableHoverEffect && _isHovered
? (Matrix4.identity()..scale(1.02))
: Matrix4.identity(),
child: ElevatedButton(
onPressed: widget.isLoading ? null : widget.onPressed,
style: ElevatedButton.styleFrom(
backgroundColor: effectiveBackgroundColor,
foregroundColor: effectiveForegroundColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(widget.borderRadius),
),
padding: widget.padding ?? const EdgeInsets.symmetric(vertical: 16),
elevation: widget.enableHoverEffect && _isHovered ? 2 : 0,
shadowColor: Colors.black.withValues(alpha: 0.08),
disabledBackgroundColor: effectiveBackgroundColor.withValues(alpha: 0.6),
),
child: widget.isLoading
? SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(
strokeWidth: 2.5,
color: effectiveForegroundColor,
),
)
: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
if (widget.icon != null) ...[
Icon(
widget.icon,
color: effectiveForegroundColor,
size: _isHovered ? 24 : 20,
),
const SizedBox(width: 8),
],
Text(
widget.text,
style: TextStyle(
fontSize: widget.fontSize,
fontWeight: FontWeight.w600,
color: effectiveForegroundColor,
),
),
],
),
),
);
if (widget.enableHoverEffect) {
return MouseRegion(
onEnter: (_) => setState(() => _isHovered = true),
onExit: (_) => setState(() => _isHovered = false),
child: button,
);
}
return button;
}
}