테마#
CoUI는 Flutter와 Web 양쪽에서 일관된 테마 시스템을 제공합니다.
Flutter 테마#
ComponentThemeData#
모든 CoUI Flutter 컴포넌트는 ComponentThemeData를 통해 테마를 받습니다:
MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
extensions: [
ComponentThemeData(
button: ButtonTheme(
borderRadius: BorderRadius.circular(8),
),
badge: BadgeTheme(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 2),
),
),
],
),
)
개별 컴포넌트 테마#
각 컴포넌트에 로컬 테마를 적용할 수 있습니다:
ComponentTheme(
data: ComponentThemeData(
card: CardTheme(
elevation: 4,
borderRadius: BorderRadius.circular(16),
),
),
child: MyWidget(),
)
styleValue 패턴#
Flutter 컴포넌트는 styleValue()로 테마 값을 해석합니다:
final effectiveRadius = styleValue(
widget.borderRadius, // 1. 위젯 직접 지정값
theme?.borderRadius, // 2. ComponentTheme 값
() => BorderRadius.circular(8), // 3. 기본값
);
Web 테마#
CoUI 테마#
CoUI Web은 35+ 내장 테마를 지원합니다:
<html data-theme="light">
<!-- 또는 -->
<html data-theme="dark">
Style Modifier 패턴#
Web 컴포넌트는 Style Modifier로 변형을 적용합니다:
Button(
style: [Button.primary, Button.lg, Button.wide],
child: text('Large Primary Button'),
)
커스텀 테마#
Tailwind CSS를 통해 커스텀 테마를 정의합니다:
[data-theme="custom"] {
--p: 262 80% 50%; /* primary */
--s: 314 72% 45%; /* secondary */
--a: 174 72% 56%; /* accent */
--n: 218 14% 22%; /* neutral */
--b1: 0 0% 100%; /* base-100 */
}
디자인 토큰#
CoUI는 coui_core의 디자인 토큰으로 시각적 일관성을 보장합니다.
CoreRadiusScale#
Border radius를 시맨틱 토큰으로 관리합니다:
// coui_core에 정의된 값
CoreRadiusScale.extraSmall // 4px — field (input)
CoreRadiusScale.small // 8px — selector (button)
CoreRadiusScale.large // 16px — box (card)
CoreRadiusScale.full // 9999px — badge (pill)
Flutter에서는 ThemeData.fromCore()가 자동으로 적용하고,
Web에서는 Tailwind rounded-sm/md/lg/full이 CoreRadiusScale과 동기화됩니다.
CoreDuration#
애니메이션 타이밍을 통일합니다:
// coui_core에 정의된 값
CoreDuration.xs // 100ms — Toggle slide
CoreDuration.short // 150ms — Button hover, Input focus
CoreDuration.normal // 200ms — Card hover, Accordion
CoreDuration.medium // 300ms — 페이지 전환
// AnimationConstants로 접근
AnimatedContainer(
duration: AnimationConstants.normal,
curve: Curves.easeInOut,
child: content,
)
// Tailwind duration 클래스로 접근
// transition-colors duration-150
// transition-shadow duration-200
Light/Dark 모드#
MaterialApp(
theme: ThemeData.light().copyWith(
extensions: [ComponentThemeData()],
),
darkTheme: ThemeData.dark().copyWith(
extensions: [ComponentThemeData()],
),
themeMode: ThemeMode.system,
)
// ThemeToggle 버튼으로 전환
ThemeController(
child: MyApp(),
)