16 KiB
16 KiB
SubManager 컬러/테마 가이드 v4 (Glass 제거, 완전 Material 3)
목표: 글래스모피어즘(반투명/블러/그라데이션)을 전면 제거하고, 전 화면/버튼/팝업을 Material 3(ColorScheme/typography/shape/elevation) 기준으로 재정렬합니다. 버튼 나열 UI를 드롭다운으로 바꾸지 않습니다. 설정 화면에 라이트/다크/시스템 모드 선택 UI를 추가합니다.
0) 현재 상태 진단(요약)
- 전역 테마: M3 사용 중(
useMaterial3: true). 라이트/다크/OLED/고대비 테마 존재. - 이슈:
ColorScheme.error가 핑크(danger)에 매핑 → 오류색으로 부적합(레드 필요). - Glass 사용처 다수(요약/분석/네비/빈상태 등): 반투명+블러+경계. 다크/저성능 장치에서 가독성·성능 저하 가능.
- 곳곳의 하드코딩 텍스트 컬러(
AppColors.darkNavy,Color(0xFF...)) 존재 → 다크에서 대비 문제 소지.
1) 원칙(신뢰·접근성·일관성)
- 신뢰: Primary는 딥 블루(#2563EB). 과장된 장식 대신 명확한 위계/역할색 사용.
- 접근성: 본문 대비 WCAG AA(4.5:1) 충족. on-colors(onPrimary/onSurface/onError…) 일관 적용.
- 일관성: 전역 ColorScheme/typography/shape/elevation 우선, 로컬 styleFrom 최소화.
- 성능/가독성: Glass 제거 → 불투명 Surface + elevation/outline 중심으로 레이어 구분.
2) 팔레트(최종)
- Primary: #2563EB / onPrimary: #FFFFFF
- Secondary: #60A5FA / onSecondary: #0B1B31(또는 onSurface)
- Tertiary(Info): #6366F1 / onTertiary: #FFFFFF
- Error: #EF4444 / onError: #FFFFFF
- Success: #22C55E / Warning: #F59E0B (둘은 ColorScheme 외 확장 토큰으로 관리)
- Light: Background #F1F5F9 / Surface #FFFFFF / SurfaceVariant #F8FAFC / OnSurface #1E293B / OnSurfaceVariant #334155 / Outline #E2E8F0
- Dark: Background #121212 / Surface #1E1E1E / OnSurface #F5F5F6 / OnSurfaceVariant #94A3B8 / Outline #3F3F46
3) 타입·라디우스·간격·음영 스케일
- Typography(권장):
- displayLarge 48 / displayMedium 40 / displaySmall 34
- headlineLarge 32 / headlineMedium 28 / headlineSmall 24
- titleLarge 20 / titleMedium 18 / titleSmall 16
- bodyLarge 16 / bodyMedium 14 / bodySmall 12
- labelLarge 14 / labelMedium 12 / labelSmall 11
- Line-height: 1.3
1.5, Letter-spacing: 헤드라인(-0.2-0.5), 본문(+0.1)
- Shape: 4(칩/태그) / 8(스위치/토글) / 12(버튼/입력) / 16(카드/시트)
- Elevation: 0(평면) / 1(구분) / 3(카드) / 6(상부 시트/다이얼로그)
- Spacing: 4 단위(8/12/16/24/32)로 수직 리듬 고정
4) Glass 제거 및 대체 규칙
lib/widgets/glassmorphism_card.dart사용부 전면 치환:- 대체:
Card(elevation: 3, color: colorScheme.surface, shape: 16) - 경계:
Outline기반(라이트 #E2E8F0, 다크 #3F3F46, 투명도 60~80%) - 섀도우: 라이트만 약하게(8~12), 다크는 outline 위주
- 대체:
- 내부 텍스트: 항상
colorScheme.onSurface또는 전역textTheme사용(하드코딩 금지) - 그라데이션/반투명 배경 삭제(필요 시 Hero/그림·아이콘 등으로 시각적 흥미 보완)
5) 컴포넌트별 가이드(누락 없음)
- AppBar: 배경=surface, 제목/아이콘=onSurface, 높이=56, 타이틀 글꼴=titleLarge
- Navigation(하단): 배경=surface, 활성 아이콘/라벨=primary, 비활성=onSurfaceVariant, 반경=16
- FAB: 배경=primary, 아이콘=onPrimary, 반경=16, elevation=6
- Buttons(Elevated/Text/Outlined): minHeight=48, 반경=12, primary=onPrimary, outline=outline, text=onSurface
- IconButton: 기본 onSurface, 강조 상태는 primary 80~90%
- Inputs(TextField/Selectors): filled 라이트=surfaceVariant, 다크=#2A2A2A, 포커스라인=primary 1.5, 에러=error 1.5~2
- Chips/Badges: 배경=역할색(primary/success/warning/error), 텍스트=onX, 반경=8
- Cards: elevation=3, 반경=16, 배경=surface, 텍스트=onSurface
- Lists/Tiles: 제목=onSurface, 보조=onSurfaceVariant, divider=outline, 타일 반경=12
- Dialogs/Sheets: 배경=surface, 제목=titleLarge, 본문=bodyMedium, 버튼=역할색+onX, elevation=6, 반경=20
- Snackbar: 배경=역할색(primary/success/warning/error), 텍스트/아이콘=onX, 모서리=12, floating
- Tooltips: 배경=onSurface, 텍스트=surface, 반경=8
- Progress: primary 사용, 트랙=onSurfaceVariant
- Charts/Analysis: 팔레트 [primary, tertiary(info), success, warning, error, secondary], 라벨=onSurface
- Categories/SMS: 카테고리 배경 위 텍스트/아이콘은 대비 계산(white 또는 onSurface) 적용
6) 설정 화면에 모드 선택 UI 추가(계획)
- 위치:
lib/screens/settings_screen.dart - 섹션명: Appearance(또는 테마)
- 구성:
Theme Mode라디오 그룹(시스템 / 라이트 / 다크)- RadioListTile 3개(버튼 나열 유지, 드롭다운 금지)
- 값:
AppThemeMode.system|light|dark - 동작:
context.read<ThemeProvider>().setThemeMode(mode)호출
- 추가 토글(유지): 큰 텍스트/모션 감소/고대비(현 Provider 연동)
샘플 코드
final themeProvider = context.read<ThemeProvider>();
Column(children: [
ListTile(title: Text('Theme Mode')),
RadioListTile(
title: Text('System'),
value: AppThemeMode.system,
groupValue: themeProvider.themeMode,
onChanged: (v) => themeProvider.setThemeMode(v!),
),
RadioListTile(
title: Text('Light'),
value: AppThemeMode.light,
groupValue: themeProvider.themeMode,
onChanged: (v) => themeProvider.setThemeMode(v!),
),
RadioListTile(
title: Text('Dark'),
value: AppThemeMode.dark,
groupValue: themeProvider.themeMode,
onChanged: (v) => themeProvider.setThemeMode(v!),
),
]);
7) 적용 순서(리스크 최소)
- 전역 스킴 교정:
ColorScheme.error레드로, textTheme onSurface 정렬 - Glass 제거:
GlassmorphismCard→Card치환(화면 단위 PR: 홈→분석→설정→세부) - 버튼/입력/스낵바/다이얼로그 on-colors 정렬, 하드코딩 텍스트 제거
- 모드 선택 UI 추가(설정 화면 라디오 그룹)
- 카테고리/차트 대비 보정 유틸 적용
- 회귀·접근성 검증(라이트/다크/시스템)
8) 검증
- 스크립트:
scripts/check.sh(format/analyze/test) - 시각: 모든 화면에서 텍스트 대비(AA) 확인, 상태(Hover/Pressed/Disabled) 점검
- 성능: Glass 제거 후 저사양 단말 스크롤/애니메이션 프레임 확인
9) 요약
- Glass 제거 + 완전 Material 3 전환으로 신뢰감, 가독성, 성능을 함께 강화합니다.
- 오류색은 레드로 통일, on-colors로 대비를 보장합니다.
- 설정에 시스템/라이트/다크 선택을 제공하고, 버튼 나열 UI는 유지합니다.
진행 현황(Work Log)
- [완료] 전역 스킴 교정:
ColorScheme.error를 레드(#EF4444)로 교정 (라이트/다크) - [완료] 스낵바 오류색 정렬:
AppSnackBar.showError가colorScheme.error사용 - [완료] 설정 화면 테마 모드 UI: System/Light/Dark SegmentedButton 추가(드롭다운/라디오 대체, M3 준수)
- [완료] Glass 제거(설정 화면):
GlassmorphismCard→Card치환 - [완료] Glass 제거(빈 상태 위젯):
EmptyStateWidget를Card기반으로 재구성 - [완료] Glass 제거(홈 요약 카드):
MainScreenSummaryCard외곽 →Card - [완료] Glass 제거(분석 카드): 월간 지출/총지출/파이차트 카드 →
Card - [완료] Glass 제거(광고 카드):
NativeAdWidget→Card - [완료] Glass 제거(추가 폼 섹션):
AddSubscriptionForm→Card - [완료] Glass 제거(SMS 권한 화면): 설명 카드 →
Card - [완료] Glass 제거(네비게이션): Floating Navigation Bar → Container + Padding(Material 기준)
- [완료] Glass 제거(메인 스캐폴드):
GlassmorphicScaffold→ Stack+Scaffold(배경 그라디언트+M3) - [진행] Glass 제거(기타): 일부 카드(예: SubscriptionCard) 잔여 사용처 점진 치환 예정
- [완료] Glass 제거(구독 카드): SubscriptionCard 래퍼를 Material Card+InkWell로 대체
- [진행] 하드코딩 텍스트 컬러 제거: 메인 요약/URL 섹션/네비/홈 로딩 인디케이터 등 onSurface/onSurfaceVariant로 정렬
- [진행] 하드코딩 컬러 정리(추가): 카테고리 관리/앱 잠금/이벤트·URL 상세 섹션 컨테이너와 텍스트를 M3(
surface,outline,onSurface)로 정렬 - [진행] 폼/셀렉터 M3 정렬: DatePickerField/CurrencySelector 색을
onSurface/primary/surfaceVariant로 통일 - [진행] Selectors: Category/BillingCycle 선택 컴포넌트의 배경/텍스트를
primary/onSurface로 정렬 - [진행] 공통 입력/라벨: BaseTextField/DatePickerField 라벨·힌트·값을
onSurface/onSurfaceVariant로 정렬 - [진행] 삭제 다이얼로그: Glass 제거, Material Dialog(표면/elevation) + on-colors 적용
- [진행] 추가 화면: 이벤트 섹션 타이틀/설명을 onSurface로 정렬
- [진행] 날짜 필드(DatePicker/Range): 라벨/값/아이콘/컨테이너를 M3 surface/outline/onSurface 계열로 치환
- [진행] 분석 카드/리스트: 보조 텍스트/경계/아이콘을 onSurfaceVariant/primary 계열로 정리
- [진행] 설정 화면: 텍스트/아이콘 색을 onSurface/onSurfaceVariant로 정리
- [진행] SMS 권한 화면: 아이콘/제목/본문을 primary/onSurface/onSurfaceVariant로 정리
- [진행] 추가 화면 AppBar/저장 버튼: 색을 onSurface/primary로 정리
- [다음] 버튼/입력/다이얼로그/스낵바의 on-colors 재점검 및 하드코딩 텍스트 컬러 제거
2025-09-10 작업 메모(Incremental)
- [완료] Settings 화면:
AppColors.*제거 →colorScheme.primary/onSurface/onSurfaceVariant적용. 알림 반복 SwitchListTile의activeColor비사용(신 APIactiveThumbColor/activeTrackColor)로 교체. - [완료] AddSubscriptionForm: CurrencySelector / BillingCycleSelector / CategorySelector의
isGlassmorphism플래그 비활성(기본 M3 경량 스타일 사용). - [완료] MainSummaryCard: 이벤트 절약액 텍스트 색상을
colorScheme.primary로 정렬. - [완료] MonthlyExpenseChartCard: 툴팁 배경/텍스트를
inverseSurface/onInverseSurface로 교체(가독성 향상). - [완료] Light Theme 카드/입력:
lib/theme/app_theme.dart의 카드 테마에서 글래스 컬러/보더 제거, elevation=1·radius=16 유지. InputDecorationTheme는surfaceVariant(light 대체 토큰) +outline/primary/error경계로 전환. - [완료] TotalExpenseSummaryCard: 아이콘 캡슐 배경을
surfaceContainerHighest+outline로 교체, 아이콘 컬러는primary사용. 복사 스낵바의 글래스 배경 제거. - [완료] DetailFormSection: 글래스 박스 →
surface+outline컨테이너로 교체, Currency/BillingCycle/Category 셀렉터의isGlassmorphism비활성. - [완료] SMS Scan SubscriptionCard:
Card(elevation:1, outline)로 교체, forceDark 텍스트 제거, 입력fillColor를surface로 통일, 카테고리 셀렉터 글래스 비활성. - [완료] SecondaryButton: Hover 배경을
onSurface6%로, 보더/텍스트를outline/primary로 정렬. - [완료] CategoryManagement: AppBar
primary/onPrimary적용, Dropdownvalue→initialValue(비권장 API 해결), 텍스트 onSurface 정렬. - [완료] Primary/SecondaryButton hover 트랜스폼:
Matrix4.scale제거 →diagonal3Values또는Transform.scale로 대체(비권장 API 해결). - [완료] RotatePageRoute 전환:
Matrix4.scale제거 → 중첩Transform.scale로 전환. - [완료] ThemedText: AppColors 의존 제거, 대비 색상 결정을
colorScheme.onSurface기반으로 단순화. - [완료] 글래스 파일 제거:
lib/widgets/glassmorphism_card.dart,lib/widgets/glassmorphic_scaffold.dart삭제(미참조 확인). - [완료] Light Theme 텍스트·컴포넌트 정렬:
app_theme.dart에서 textTheme를 M3 기본 +onSurface컬러로 일괄 정렬. Switch/Checkbox/Radio/Slider/TabBar/Divider를ColorScheme기반으로 리팩터. - [완료] AddSubscriptionAppBar: const 적용(경고 제거),
scripts/check.sh전체 통과 확인. - [완료] Dark/OLED 테마 정리:
adaptive_theme.dart에서 다크 텍스트·컴포넌트(M3 on-colors) 정렬, Input/Buttons/TabBar/Divider/Switch/Checkbox/Radio/Slider를 ColorScheme 기준으로 통일. OLED는 surface/배경만 블랙 톤으로 보정. - [완료] ThemedText: Glass 마커 제거(Indicator/Wrapper 삭제), 대비 로직 단순화.
- [완료] Charts: 월간 바차트 색상
ColorScheme.primary/secondary로 전환, 그리드/백바onSurfaceVariant사용. 파이차트 팔레트는ColorScheme(primary/secondary/tertiary/error)+success/warning 상수로 정리. - [완료] Settings/SubscriptionCard: 글래스 위젯 의존 제거 → Material Card + InkWell로 치환(중첩 Padding은 ListTile의
contentPadding사용). - [완료] Settings 색 정리 마무리: 모든 텍스트/아이콘/보더/드롭다운을
onSurface/onSurfaceVariant/primary/surface로 통일. - [완료] 전역 그라데이션 제거: EmptyState/FloatingNav Add/MainSummary 이벤트 배지/Detail Header/Detail 편집 안내/SubscriptionCard 헤더·이벤트 배지/Add 화면 헤더/Splash 배경, 로고/파티클 장식 등 모든 Linear/Radial gradient 삭제. 단색은
primary/surface/surfaceContainer*/semantic(error, warning)로 대체. - [완료] 차트 막대 그라데이션 제거: 단색
primary로 통일. - [검증]
scripts/check.sh실행: 포맷 자동 적용 후 정적 분석 info 수준 경고만 존재(주요activeColor비권장 항목 해결됨).
2025-09-11 작업 메모(Incremental)
- [완료] BillingCycleSelector: 선택 배경=primary, 텍스트=onPrimary, 비선택 배경=surface, 보더=outline(60%); glass/gradient 파라미터는 비사용 처리(호환 유지).
- [완료] CurrencySelector: 동일한 M3 패턴으로 정리(표면/윤곽선/온컬러), isGlassmorphism 무시.
- [완료] CategorySelector: 선택 시 baseColor가 있으면 사용, 없으면 primary; 나머지는 surface/outline/onSurface.
- [완료] AnalysisBadge: AppColors 제거 → surface 배경 + outline 보더 + 은은한 블랙 섀도(8%).
- [완료] SubscriptionCard:
- 상단 스트립: event=error, 결제 임박=warning, 그 외=카테고리 색.
- 가격: 이벤트 원가=onSurfaceVariant 취소선, 현재가=error, 일반가=primary.
- 결제 예정 뱃지: success/warning(확장 토큰) 사용, 배경은 10% 알파.
- 결제 주기 뱃지: surface + outline, 텍스트 onSurfaceVariant.
- [검증]
scripts/check.sh전체 통과(Format/Analyze/Test OK).
2025-09-11 추가 배치
- [완료] AppLock/Main 화면 스낵바: ColorScheme.error/success + onPrimary 텍스트로 통일.
- [완료] AddSubscriptionEventSection: info 박스
tertiary로, 아이콘도 동일 컬러. - [완료] DetailEventSection: 초록 상수 제거 →
colorScheme.success/onPrimary. - [완료] SMS Scan 위젯: 로딩 인디케이터/버튼을
primary기반으로. - [완료] SubscriptionPieChartCard: AppColors 제거, 팔레트는
primary/success/warning/error/tertiary/secondary+ 화이트 라벨. 환율 배지는primary소프트 톤. - [완료] EventAnalysisCard: 현재가/할인율 배지 색을
success/error로 정리. - [완료] TotalExpenseSummaryCard: 아이콘을
success로 정리. - [완료] Splash: overlay/파티클/타이틀/서브타이틀/인디케이터를 ColorScheme 기반으로 단순화(파티클 색은 렌더 시
primary). - [검증]
scripts/check.sh재실행 통과.
2025-09-11 Dark Theme 정리
- [완료] adaptive_theme.dart 다크 테마를 전면 ColorScheme 기반으로 재정렬:
- InputDecorationTheme: fill=surface, border=outline/primary/error, label/hint=onSurfaceVariant.
- Elevated/Switch/Checkbox/Radio/Slider/TabBar/Divider: scheme 값 사용.
- AppBar/Card: 배경=surface, 전경/테두리=scheme on/outline.
- OLED 테마는 surface만 더 어둡게 덮어쓰기.
- [검증]
scripts/check.sh통과.
2025-09-11 Light Theme 추가 정리
- [완료] app_theme.dart 라이트 테마를 ColorScheme 기반으로 정리:
- InputDecorationTheme: fill=surface, border=outline/primary/error, label/hint=onSurfaceVariant.
- Elevated/Text/Outlined/FAB: primary/onPrimary, Outlined 보더=outline.
- SnackBarTheme: primary/onPrimary.
- Scaffold 배경은 기존 디자인(#F1F5F9)을 유지(직접 지정).
- [검증]
scripts/check.sh재실행 통과.