테마 | CoUI

테마

CoUI 테마 시스템 가이드

테마#

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(),
)