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>
This commit is contained in:
@@ -2,12 +2,12 @@ import 'package:flutter/material.dart';
|
||||
|
||||
class AppColors {
|
||||
// 메인 컬러 (Metronic Tailwind 스타일)
|
||||
static const primaryColor = Color(0xFF3B82F6); // 메트로닉 블루
|
||||
static const secondaryColor = Color(0xFF64748B); // 슬레이트 600
|
||||
static const successColor = Color(0xFF10B981); // 그린
|
||||
static const primaryColor = Color(0xFF2563EB); // 딥 블루
|
||||
static const secondaryColor = Color(0xFF60A5FA); // 스카이 블루
|
||||
static const successColor = Color(0xFF38BDF8); // 소프트 민트
|
||||
static const infoColor = Color(0xFF6366F1); // 인디고
|
||||
static const warningColor = Color(0xFFF59E0B); // 앰버
|
||||
static const dangerColor = Color(0xFFEF4444); // 레드
|
||||
static const dangerColor = Color(0xFFF472B6); // 핑크 액센트
|
||||
|
||||
// 배경색
|
||||
static const backgroundColor = Color(0xFFF1F5F9); // 슬레이트 100
|
||||
@@ -17,18 +17,24 @@ class AppColors {
|
||||
|
||||
// 텍스트 컬러
|
||||
static const textPrimary = Color(0xFF1E293B); // 슬레이트 800
|
||||
static const textSecondary = Color(0xFF64748B); // 슬레이트 600
|
||||
static const textMuted = Color(0xFF94A3B8); // 슬레이트 400
|
||||
static const darkNavy = Color(0xFF1E293B); // 메인 텍스트 (color.md 가이드)
|
||||
static const textSecondary = Color(0xFF334155); // 네이비 그레이
|
||||
static const navyGray = Color(0xFF334155); // 서브 텍스트 (color.md 가이드)
|
||||
static const textMuted = Color(0xFF334155); // 네이비 그레이
|
||||
static const textLight = Color(0xFFFFFFFF); // 화이트
|
||||
static const pureWhite = Color(0xFFFFFFFF); // 버튼 텍스트용 (color.md 가이드)
|
||||
|
||||
// 보더 & 디바이더
|
||||
static const borderColor = Color(0xFFE2E8F0); // 슬레이트 200
|
||||
static const dividerColor = Color(0xFFE2E8F0); // 슬레이트 200
|
||||
|
||||
// 그림자 (color.md 가이드)
|
||||
static const shadowBlack = Color(0x14000000); // rgba(0,0,0,0.08) - 8% opacity
|
||||
|
||||
// 그라데이션 컬러 - 다양한 효과를 위한 조합
|
||||
static const List<Color> blueGradient = [
|
||||
Color(0xFF3B82F6),
|
||||
Color(0xFF2563EB)
|
||||
Color(0xFF2563EB), // 딥 블루
|
||||
Color(0xFF60A5FA) // 스카이 블루
|
||||
];
|
||||
static const List<Color> tealGradient = [
|
||||
Color(0xFF14B8A6),
|
||||
@@ -48,10 +54,10 @@ class AppColors {
|
||||
];
|
||||
|
||||
// Glassmorphism 효과를 위한 색상
|
||||
static const glassSurface = Color(0x0FFFFFFF); // 매우 연한 흰색 (6% opacity)
|
||||
static const glassBackground = Color(0x1AFFFFFF); // 연한 흰색 (10% opacity)
|
||||
static const glassSurface = Color(0x33FFFFFF); // 화이트 글래스 (20% opacity)
|
||||
static const glassBackground = Color(0x33FFFFFF); // 화이트 글래스 (20% opacity)
|
||||
static const glassCard = Color(0x33FFFFFF); // 반투명 흰색 (20% opacity)
|
||||
static const glassBorder = Color(0x4DFFFFFF); // 반투명 테두리 (30% opacity)
|
||||
static const glassBorder = Color(0xFF2563EB); // 딥 블루 테두리
|
||||
static const glassOverlay = Color(0x0D000000); // 연한 검정 오버레이 (5% opacity)
|
||||
|
||||
// 다크 모드용 Glassmorphism 색상
|
||||
@@ -62,8 +68,8 @@ class AppColors {
|
||||
|
||||
// 백드롭 블러 효과를 위한 그라디언트
|
||||
static const List<Color> glassGradient = [
|
||||
Color(0x33FFFFFF), // 20% white
|
||||
Color(0x1AFFFFFF), // 10% white
|
||||
Color(0x0FFFFFFF), // 6% white
|
||||
];
|
||||
|
||||
static const List<Color> glassGradientDark = [
|
||||
@@ -71,6 +77,18 @@ class AppColors {
|
||||
Color(0x0F000000), // 6% black
|
||||
];
|
||||
|
||||
// 메인 그라데이션
|
||||
static const List<Color> mainGradient = [
|
||||
Color(0xFF2563EB), // 딥 블루
|
||||
Color(0xFF60A5FA), // 스카이 블루
|
||||
Color(0xFFE0E7EF), // 라이트 그레이
|
||||
];
|
||||
|
||||
static const List<Color> accentGradient = [
|
||||
Color(0xFF38BDF8), // 소프트 민트
|
||||
Color(0xFF60A5FA), // 스카이 블루
|
||||
];
|
||||
|
||||
// 시간대별 배경 그라디언트
|
||||
static const List<Color> morningGradient = [
|
||||
Color(0xFFFED7AA), // 따뜻한 오렌지
|
||||
|
||||
@@ -17,22 +17,22 @@ class AppTheme {
|
||||
// 기본 배경색
|
||||
scaffoldBackgroundColor: AppColors.backgroundColor,
|
||||
|
||||
// 카드 스타일 - 부드러운 그림자, 둥근 모서리
|
||||
// 카드 스타일 - 글래스모피즘 효과
|
||||
cardTheme: CardTheme(
|
||||
color: AppColors.cardColor,
|
||||
elevation: 1,
|
||||
shadowColor: Colors.black.withValues(alpha: 0.04),
|
||||
color: AppColors.glassCard,
|
||||
elevation: 0,
|
||||
shadowColor: AppColors.shadowBlack,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
side: const BorderSide(color: AppColors.borderColor, width: 0.5),
|
||||
side: const BorderSide(color: AppColors.glassBorder, width: 1),
|
||||
),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
||||
),
|
||||
|
||||
// 앱바 스타일 - 깔끔하고 투명한 디자인
|
||||
// 앱바 스타일 - 글래스모피즘 디자인
|
||||
appBarTheme: const AppBarTheme(
|
||||
backgroundColor: AppColors.surfaceColor,
|
||||
backgroundColor: Colors.transparent,
|
||||
foregroundColor: AppColors.textPrimary,
|
||||
elevation: 0,
|
||||
centerTitle: false,
|
||||
@@ -43,7 +43,7 @@ class AppTheme {
|
||||
letterSpacing: -0.2,
|
||||
),
|
||||
iconTheme: const IconThemeData(
|
||||
color: AppColors.secondaryColor,
|
||||
color: AppColors.primaryColor,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
@@ -52,21 +52,21 @@ class AppTheme {
|
||||
textTheme: const TextTheme(
|
||||
// 헤드라인 - 페이지 제목
|
||||
headlineLarge: const TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
color: AppColors.darkNavy, // color.md 가이드: 메인 텍스트
|
||||
fontSize: 32,
|
||||
fontWeight: FontWeight.w700,
|
||||
letterSpacing: -0.5,
|
||||
height: 1.2,
|
||||
),
|
||||
headlineMedium: const TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
color: AppColors.darkNavy, // color.md 가이드: 메인 텍스트
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.w700,
|
||||
letterSpacing: -0.5,
|
||||
height: 1.2,
|
||||
),
|
||||
headlineSmall: const TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
color: AppColors.darkNavy, // color.md 가이드: 메인 텍스트
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: -0.25,
|
||||
@@ -75,21 +75,21 @@ class AppTheme {
|
||||
|
||||
// 타이틀 - 카드, 섹션 제목
|
||||
titleLarge: const TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
color: AppColors.darkNavy, // color.md 가이드: 메인 텍스트
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: -0.2,
|
||||
height: 1.4,
|
||||
),
|
||||
titleMedium: TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
color: AppColors.darkNavy, // color.md 가이드: 메인 텍스트
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: -0.1,
|
||||
height: 1.4,
|
||||
),
|
||||
titleSmall: TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
color: AppColors.darkNavy, // color.md 가이드: 메인 텍스트
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: 0,
|
||||
@@ -98,21 +98,21 @@ class AppTheme {
|
||||
|
||||
// 본문 텍스트
|
||||
bodyLarge: TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
color: AppColors.darkNavy, // color.md 가이드: 메인 텍스트
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
letterSpacing: 0.1,
|
||||
height: 1.5,
|
||||
),
|
||||
bodyMedium: TextStyle(
|
||||
color: AppColors.textSecondary,
|
||||
color: AppColors.navyGray, // color.md 가이드: 서브 텍스트
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
letterSpacing: 0.1,
|
||||
height: 1.5,
|
||||
),
|
||||
bodySmall: TextStyle(
|
||||
color: AppColors.textMuted,
|
||||
color: AppColors.navyGray, // color.md 가이드: 서브 텍스트
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
letterSpacing: 0.2,
|
||||
@@ -121,21 +121,21 @@ class AppTheme {
|
||||
|
||||
// 라벨 텍스트
|
||||
labelLarge: TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
color: AppColors.darkNavy, // color.md 가이드: 메인 텍스트
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: 0.1,
|
||||
height: 1.4,
|
||||
),
|
||||
labelMedium: TextStyle(
|
||||
color: AppColors.textSecondary,
|
||||
color: AppColors.navyGray, // color.md 가이드: 서브 텍스트
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: 0.2,
|
||||
height: 1.4,
|
||||
),
|
||||
labelSmall: TextStyle(
|
||||
color: AppColors.textMuted,
|
||||
color: AppColors.navyGray, // color.md 가이드: 서브 텍스트
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w500,
|
||||
letterSpacing: 0.2,
|
||||
@@ -143,10 +143,10 @@ class AppTheme {
|
||||
),
|
||||
),
|
||||
|
||||
// 입력 필드 스타일 - 깔끔하고 현대적인 디자인
|
||||
// 입력 필드 스타일 - 글래스모피즘 디자인
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
filled: true,
|
||||
fillColor: AppColors.surfaceColorAlt,
|
||||
fillColor: AppColors.glassBackground,
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
@@ -154,7 +154,7 @@ class AppTheme {
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderSide: const BorderSide(color: AppColors.borderColor, width: 1),
|
||||
borderSide: const BorderSide(color: AppColors.textSecondary, width: 1),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
@@ -224,13 +224,13 @@ class AppTheme {
|
||||
// 아웃라인 버튼 스타일
|
||||
outlinedButtonTheme: OutlinedButtonThemeData(
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: AppColors.textPrimary,
|
||||
foregroundColor: AppColors.primaryColor,
|
||||
minimumSize: const Size(0, 48),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
side: const BorderSide(color: AppColors.borderColor, width: 1),
|
||||
side: const BorderSide(color: AppColors.secondaryColor, width: 1),
|
||||
textStyle: const TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w600,
|
||||
@@ -265,7 +265,7 @@ class AppTheme {
|
||||
}),
|
||||
trackColor: MaterialStateProperty.resolveWith<Color>((states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return AppColors.primaryColor.withValues(alpha: 0.5);
|
||||
return AppColors.secondaryColor.withValues(alpha: 0.5);
|
||||
}
|
||||
return AppColors.borderColor;
|
||||
}),
|
||||
@@ -282,7 +282,7 @@ class AppTheme {
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
side: const BorderSide(color: AppColors.borderColor, width: 1.5),
|
||||
side: const BorderSide(color: AppColors.secondaryColor, width: 1.5),
|
||||
),
|
||||
|
||||
// 라디오 버튼 스타일
|
||||
@@ -291,16 +291,16 @@ class AppTheme {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return AppColors.primaryColor;
|
||||
}
|
||||
return AppColors.borderColor;
|
||||
return AppColors.textSecondary;
|
||||
}),
|
||||
),
|
||||
|
||||
// 슬라이더 스타일
|
||||
sliderTheme: SliderThemeData(
|
||||
activeTrackColor: AppColors.primaryColor,
|
||||
inactiveTrackColor: AppColors.borderColor,
|
||||
inactiveTrackColor: AppColors.textSecondary,
|
||||
thumbColor: AppColors.primaryColor,
|
||||
overlayColor: AppColors.primaryColor.withValues(alpha: 0.2),
|
||||
overlayColor: AppColors.primaryColor.withValues(alpha: 0.3),
|
||||
trackHeight: 4,
|
||||
thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 10),
|
||||
overlayShape: const RoundSliderOverlayShape(overlayRadius: 20),
|
||||
|
||||
Reference in New Issue
Block a user