다크 모드
다크 테마의 설계 원칙과 시멘틱 오버라이드 규칙. 모든 텍스트 페어의 WCAG AA는 자동 테스트가 보증합니다.
마지막 업데이트 2026-06-12
설계 원칙#
다크는 "색 반전"이 아니라 시멘틱 재설계입니다. P2에서 확정했습니다.
- semantic만 오버라이드 — primitive 램프는 두 테마가 공유합니다 (구조: 시드 B / 값: 시드 A 램프)
[data-theme='dark']가 전환 단위 — 중첩 가능(문서 안의 데모 패널이 반대 테마를 강제할 수 있음)color-scheme선언으로 네이티브 폼 컨트롤·스크롤바도 함께 전환됩니다- Flutter는 같은 SSOT의
WizColors.dark를 사용합니다
다크 전환 규칙 4가지#
① 인터랙션은 밝아진다#
라이트에서 hover는 어두워지고(600→700), 다크에서는 밝아집니다(500→400).
Primary 자체도 한 단계 밝은 blue.500을 씁니다 — 600은 다크 표면에서 침침합니다.
② Primary 채움 위 잉크는 반전된다#
다크의 primary(blue.500) 위 백색 텍스트는 2.96:1로 읽기 어렵습니다.
on-primary는 다크에서 gray.900(다크 잉크)으로 반전됩니다 — Material 다크 관례와 동일.
Primary 버튼
③ 상태색은 -400 램프로 갈아탄다#
원색(500/600)은 다크 표면에서 대비가 부족합니다. 다크의 상태 표시·텍스트는
모두 -400 틴트를 사용합니다 (green-400 · amber-400 · red-400 · sky-400).
④ 그림자 대신 보더와 표면 위계#
다크에서 그림자는 거의 보이지 않습니다. 떠 있는 표면은 올라올수록 밝아져
위계를 만듭니다(M3 다크 규칙). surface-raised는 다크에서 neutral-tonal.t22 —
surface(gray.800 ≈ 톤 16)보다 한 단계 밝은 톤으로, ADR-013 이전의 손으로 끼운
gray.750 중간 단계를 톤 수학 파생이 대체했습니다. 그림자 토큰은 두 테마
공통(core)으로 유지됩니다.
서피스 위계#
표면 토큰은 톤(neutral L*)이 올라가며 위계를 만듭니다. 다크는 라이트의 역방향 —
배경이 가장 어둡고, 올라온 표면일수록 밝습니다.
| 역할 | 라이트 | 다크 | 다크 톤 |
|---|---|---|---|
| bg (페이지) | gray.50 | gray.900 | ≈ t8 |
| surface (콘텐츠) | white | gray.800 | ≈ t16 |
| surface-raised (떠 있음) | white + 그림자 | neutral-tonal.t22 | t22 |
| surface-muted | gray.100 | gray.700 | ≈ t27 |
| surface-selected | blue.50 | blue.900 | — |
- t8bg
- t16surface
- t22raised
- t27muted
톤 번호 = CIELAB L*(지각 명도, D65) — 0 검정 → 100 흰색. 같은 번호는 모든 hue에서 같은 명도라 대비가 톤 차이로 결정됩니다.
상태 레이어 (hover · pressed)#
surface-hover·surface-pressed는 더 이상 손으로 고른 gray 단계가 아닙니다.
M3 state layer 수식 — 콘텐츠 색(text)을 표면 위에 **hover 8% · pressed 12%**로
합성 — 으로 scripts/build-tokens/src/state-layer.ts가 빌드 타임에 생성합니다.
테마의 text/surface만 정하면 양 상태가 자동 파생되고, "다크는 밝아진다"가 수식에서
공짜로 나옵니다(다크 잉크는 밝은 gray.50이라 어두운 표면을 밝히는 방향).
AA 자동 검증#
scripts/build-tokens/test/contrast.test.ts가 텍스트/UI 페어 매트릭스를
양 테마에서 매 빌드 검증합니다 — 텍스트 4.5:1, 비텍스트 UI 3:1.
*-text·text·text-muted 계열은 명명 규약 기반 자동 페어라 신규 토큰도
등록 없이 보호됩니다. 토큰 값을 바꾸면 대비 미달이 빌드에서 즉시 실패합니다.
의도된 예외(사용 규칙으로 관리 — 게이트 비대상):
- 상태 원색(success/warning/error/info)은 표시 전용 — 텍스트는
*-text토큰만. 특히 라이트 warning(amber.500)은 비텍스트 3:1도 미달(2.15) — 단색 아이콘/보더 단독 사용 금지, 항상 형태·라벨과 중복 표현 disabled-*페어 — WCAG 1.4.3/1.4.11 inactive 면제(의도적 비대상)text-subtle은 bg/surface 전용 — muted 표면에는text-muted사용- Primary 600 + 백색은 large text(≥24px 또는 ≥18.66px bold) 전용 (DD-6 정책)
시멘틱 토큰 — 양 테마 값#
| 토큰 | 라이트 | 다크 | 설명 |
|---|---|---|---|
| — | |||
| — | |||
| — | |||
| — | |||
| AA 안전 채움 — 일반 크기(16px) 텍스트 버튼용 (DD-6 정책, P3 신설) | |||
| — | |||
| — | |||
| 소형 텍스트용 Primary — bg·surface·surface-selected·primary-subtle 표면에서 AA 보장(매트릭스 고정). surface-muted 위 사용 금지 | |||
| — | |||
| — | |||
| — | |||
| — | |||
| nav 활성/선택 표면(블루 틴트) | |||
| 떠 있는 표면(그림자로 위계) | |||
| — | |||
| — | |||
| — | |||
| P2 의도 변경(시드 gray.400→500) — 400은 백색 입력면에서 2.54:1, placeholder도 텍스트(AA 대상). parity 예외 기록 | |||
| — | |||
| — | |||
| 옅은 구분선/보더 | |||
| — | |||
| — | |||
| P2 의도 변경(시드 blue.600→700) — 600은 모든 라이트 표면에서 4.39:1로 AA 미달. parity 예외 목록 기록 | |||
| P2 의도 변경(시드 blue.700→800) — link 승격에 따른 hover 단계 이동 | |||
| 상태 표시(아이콘/보더/배지) — 텍스트는 success-text 사용 | |||
| 상태 표시 전용 — 라이트 표면 텍스트/단독 아이콘 금지(대비 2.2:1), warning-text + 아이콘 병용 | |||
| 상태 표시 — 텍스트는 error-text 사용 | |||
| 상태 표시 — 텍스트는 info-text 사용 | |||
| 상태 텍스트 — AA 4.5:1 (P2 신설) | |||
| 상태 텍스트 — AA 4.5:1 (P2 신설) | |||
| 상태 텍스트 — AA 4.5:1 (P2 신설) | |||
| 상태 텍스트 — AA 4.5:1 (P2 신설) | |||
| 비활성 컨트롤 배경 (P1 신설) | |||
| 비활성 컨트롤 전경 (P1 신설) | |||
| 모달/드로어 스크림 (P1 신설) | |||
| 본문 검색어 하이라이트 배경 — ::highlight(wds-search) (P1 신설) | |||
| A1 신설 — 보조 키 컬러(브랜드 시안 인접). M3 base tone40(라이트) | |||
| A1 신설 — secondary 채움 위 잉크. M3 on-base tone100 | |||
| A1 신설 — 보조 컨테이너 표면. M3 container tone90 | |||
| A1 신설 — secondary-container 위 잉크. M3 on-container tone10 | |||
| A1 신설 — 3차 키 컬러(primary +60° 회전). M3 base tone40(라이트) | |||
| A1 신설 — tertiary 채움 위 잉크. M3 on-base tone100 | |||
| A1 신설 — 3차 컨테이너 표면. M3 container tone90 | |||
| A1 신설 — tertiary-container 위 잉크. M3 on-container tone10 | |||
| A1 신설 — primary 컨테이너 표면(기존 primary-subtle와 별개의 on- 페어 보유 컨테이너). M3 container 대응 | |||
| A1 신설 — primary-container 위 잉크. M3 on-container 대응 | |||
| A1 신설 — surface-container 5티어 최저(가장 밝음). M3 light tone100. 이 5티어가 surface 톤 SSOT(00 §3.2) — Track B 머티리얼 매핑은 5-4 결정 | |||
| A1 신설 — surface-container 티어 low. M3 light tone96 | |||
| A1 신설 — surface-container 티어 기본. M3 light tone94 | |||
| A1 신설 — surface-container 티어 high. M3 light tone92 | |||
| A1 신설 — surface-container 티어 최고. M3 light tone90 | |||
| A1 신설 — M3 outline(경계/구분 UI). surface 위 UI 3:1. M3 light tone50 | |||
| A1 신설 — M3 outline-variant(장식 디바이더). 비게이트(저대비 의도, border-subtle와 동급). M3 light tone80 | |||
| A1 신설 — 반전 표면(스낵바/토스트). M3 light tone20 | |||
| A1 신설 — inverse-surface 위 잉크. M3 light tone95 | |||
| A1 신설 — inverse-surface 위 primary 액센트(다크 primary tone). M3 light=tone80 | |||
| A1 신설 — 에러 컨테이너 표면(기존 error 표시색과 별개의 컨테이너 페어). M3 container tone90 | |||
| A1 신설 — error-container 위 잉크. M3 on-container tone10 | |||
| 서포팅 액센트 사용 토큰 — 태그/카테고리 칩 배경(violet). text와 AA 4.5:1(contrast.test 게이트). UI 본문 색 아님(절제) | |||
| tag-violet-bg 위 라벨/아이콘 잉크 — AA 4.5:1 | |||
| 솔리드 채움(아바타/도트/카테고리 점) — 그래픽 요소. 본문 텍스트 배경 아님(대형 텍스트만) | |||
| 서포팅 액센트 사용 토큰 — 태그/카테고리 칩 배경(teal). text와 AA 4.5:1 | |||
| tag-teal-bg 위 라벨/아이콘 잉크 — AA 4.5:1 | |||
| 솔리드 채움(아바타/도트) — 그래픽 요소 | |||
| 서포팅 액센트 사용 토큰 — 태그/카테고리 칩 배경(magenta). text와 AA 4.5:1 | |||
| tag-magenta-bg 위 라벨/아이콘 잉크 — AA 4.5:1 | |||
| 솔리드 채움(아바타/도트) — 그래픽 요소 | |||
| 서포팅 액센트 사용 토큰 — 태그/카테고리 칩 배경(orange). Warning(amber)과 용도 구분: 장식·카테고리. text와 AA 4.5:1 | |||
| tag-orange-bg 위 라벨/아이콘 잉크 — AA 4.5:1 | |||
| 솔리드 채움(아바타/도트) — 그래픽 요소 | |||
| 서포팅 액센트 사용 토큰 — 태그/카테고리 칩 배경(cyan). text와 AA 4.5:1 | |||
| tag-cyan-bg 위 라벨/아이콘 잉크 — AA 4.5:1 | |||
| 솔리드 채움(아바타/도트) — 그래픽 요소 | |||
| 상태 컨테이너 — 연한 Success 표면(부드러운 알림/배지 바탕). M3 container tone90 | |||
| success-container 위 잉크. M3 on-container tone10 (AA) | |||
| 상태 컨테이너 — 연한 Warning 표면. M3 container tone90 | |||
| warning-container 위 잉크. M3 on-container tone10 (AA) | |||
| 상태 컨테이너 — 연한 Info 표면. M3 container tone90 | |||
| info-container 위 잉크. M3 on-container tone10 (AA) | |||
| 수식 생성(state-layer.ts) — text 8% over surface (M3 state layer, ADR-013 T3) | |||
| 수식 생성(state-layer.ts) — text 12% over surface (M3 state layer, ADR-013 T3) |
Theme Architecture (예고)#
테마는 4계층으로 확장됩니다 — Foundation → WIZ Default → Customer → Enterprise. semantic 오버라이드 계층으로 실현하며(지금의 light/dark와 동일 메커니즘), MVP 범위 밖으로 구조만 보장합니다. 상세는 MASTER_PLAN §5-④.