디자인 토큰
Primitive → Semantic → Component 3계층 토큰의 구조와 규칙, Web/Flutter 소비 방법. 한 곳(JSON SSOT)을 고치면 두 플랫폼이 함께 바뀝니다.
마지막 업데이트 2026-06-12
3계층 구조#
토큰 정본은 tokens/ 디렉토리의 W3C Design Tokens JSON 하나입니다(AD-2).
codegen(make tokens)이 CSS 변수와 Dart 상수를 동시에 생성합니다.
blue.600#1A75EB · literalalias 금지color.primary→ blue.600core만 참조checkbox.bg-checked→ color.primarysemantic만 참조| 계층 | 참조 규칙 | 위반 시 |
|---|---|---|
| core | literal만 (alias 금지) | 빌드 실패 |
| semantic | core만 참조 | 빌드 실패 |
| component | semantic만 참조 (primitive 직접 참조 금지 — AD-2 #4) | 빌드 실패 |
토널 램프 (Primitive 생성)#
core 램프는 손으로 고른 hex가 아니라 톤 수학으로 생성됩니다(ADR-013). 톤 번호는
곧 CIELAB L*(지각 명도, D65) — t40은 모든 hue에서 같은 명도라, 두 색의 대비가
톤 차이만으로 결정됩니다. Material 3의 tonal palette와 같은 정의를 HCT 엔진 없이
scripts/build-tokens/src/tonal.ts(culori lch65)로 구현했습니다.
- t22다크 surface-raised (tone 수학 파생)
- t40M3 라이트 전경 기준
- t80M3 다크 전경 기준
톤 번호 = CIELAB L*(지각 명도, D65) — 0 검정 → 100 흰색. 같은 번호는 모든 hue에서 같은 명도라 대비가 톤 차이로 결정됩니다.
색 램프는 표준 13톤입니다 — t40(라이트 기준)과 t80(다크 기준)의 대칭이 테마 전환
공식이 됩니다.
- t40라이트 primary
- t80다크 primary
톤 번호 = CIELAB L*(지각 명도, D65) — 0 검정 → 100 흰색. 같은 번호는 모든 hue에서 같은 명도라 대비가 톤 차이로 결정됩니다.
톤 번호 = CIELAB L*(지각 명도, D65) — 0 검정 → 100 흰색. 같은 번호는 모든 hue에서 같은 명도라 대비가 톤 차이로 결정됩니다.
톤 번호 = CIELAB L*(지각 명도, D65) — 0 검정 → 100 흰색. 같은 번호는 모든 hue에서 같은 명도라 대비가 톤 차이로 결정됩니다.
톤 번호 = CIELAB L*(지각 명도, D65) — 0 검정 → 100 흰색. 같은 번호는 모든 hue에서 같은 명도라 대비가 톤 차이로 결정됩니다.
톤 번호 = CIELAB L*(지각 명도, D65) — 0 검정 → 100 흰색. 같은 번호는 모든 hue에서 같은 명도라 대비가 톤 차이로 결정됩니다.
램프는 승인된 기존 팔레트의 실측 (L*, C, H) 프로파일을 보간해 생성합니다 — 체계화이지
리베이스가 아닙니다. 빌드 게이트가 앵커 충실도(기존 색을 채널 Δ≤2로 재현)와 톤 대비
법칙(Δtone≥50 → 4.4:1, 명시 전경/배경 페어 → 4.5:1)을 매 빌드 검증합니다. 새 브랜드
컬러는 프로파일 한 줄이면 전체 톤·상태 레이어가 자동 파생됩니다.
네이밍#
JSON 경로가 그대로 CSS 변수명과 Dart 상수명이 됩니다.
| JSON 경로 | CSS | Dart |
|---|---|---|
blue.600 | --wds-blue-600 | WizPalette.blue600 |
color.primary | --wds-color-primary | WizColors.light.primary / .dark.primary |
font.size.body-1 | --wds-font-size-body-1 | WizTypography.sizeBody1 |
space.4 | --wds-space-4 | WizSpacing.s4 |
button.bg | --wds-button-bg | WizButtonTokens.light.bg |
사용법#
Web — CSS 변수#
alias는 var() 참조로 유지됩니다(테마 전환은 [data-theme]가 처리).
.card {
background: var(--wds-color-surface);
border-radius: var(--wds-radius-md);
padding: var(--wds-space-6);
box-shadow: var(--wds-shadow-sm);
}
Flutter — 생성 상수#
Dart 타겟은 빌드타임에 평면화됩니다 — rem은 px(×16) double로, shadow는
BoxShadow로, duration은 Duration으로, 이징은 Cubic으로 변환됩니다.
import 'package:wiz_ui/wiz_ui.dart';
Container(
color: WizColors.light.surface, // 다크: WizColors.dark.surface
padding: const EdgeInsets.all(WizSpacing.s6),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(WizRadius.md),
boxShadow: const [WizShadows.sm],
),
)
두 타겟의 일치는 교차 타겟 테스트가 보증합니다 — 모든 시멘틱 컬러의 light/dark computed 값이 CSS와 Dart에서 동일함을 매 빌드 검증.
시멘틱 컬러 전체#
라이트가 정본, 다크는 오버라이드입니다. 상세 설계 근거는 다크 모드 참조.
| 토큰 | 라이트 | 다크 | 설명 |
|---|---|---|---|
컴포넌트 토큰#
semantic만 참조합니다 — 테마는 참조 경로를 따라 자동 적용됩니다.
| 토큰 | 값 | 설명 |
|---|---|---|
변경 절차#
토큰 변경은 영향 등급(Token Impact Matrix)에 따라 차등 승인됩니다 — Primitive 변경은 Governance Board 승인(High), 문서 수정은 Owner 승인(Low). 전체 절차는 MASTER_PLAN §12 참조.
P2 확정 기록#
| 항목 | 결정 | 근거 |
|---|---|---|
| Blue 700 표기 모호 | #1252B2 확정 | 시각 대조 — #125282(라벨)는 램프 hue 연속성 파괴 |
| Warning 표기 모호 | #F59E0B 확정 | 두 후보 시각 구분 불가 — 업계 표준값 채택 |
color.link | blue.600 → 700 승격 (의도 변경) | 600은 모든 라이트 표면에서 4.39:1 — AA 미달 |
color.on-primary(다크) | white → gray.900 반전 | 다크 primary(blue.500) 위 백색은 2.96:1 |
color.text-placeholder | 라이트 gray.400→500 / 다크 500→400 (의도 변경) | placeholder도 텍스트 — 시드값은 백색 입력면 2.54:1 |
| Button 600+백색 (DD-6) | large text 전용 정책 | 4.39:1 ≥ 3:1(large) — 일반 텍스트 버튼은 P3에서 strong 변형 |