Dark ModeP2 본문

다크 모드

다크 테마의 설계 원칙과 시멘틱 오버라이드 규칙. 모든 텍스트 페어의 WCAG AA는 자동 테스트가 보증합니다.

마지막 업데이트 2026-06-24

설계 원칙#

다크는 “색 반전”이 아니라 시멘틱 재설계입니다. P2에서 확정했습니다.

  • semantic만 오버라이드 — primitive 램프는 두 테마가 공유합니다 (구조: 시드 B / 값: 시드 A 램프)
  • [data-theme='dark'] 가 전환 단위 — 중첩 가능(문서 안의 데모 패널이 반대 테마를 강제할 수 있음)
  • color-scheme 선언으로 네이티브 폼 컨트롤·스크롤바도 함께 전환됩니다
  • Flutter는 같은 SSOT의 WizColors.dark를 사용합니다

다크 전환 규칙 4가지#

① 인터랙션은 밝아진다#

라이트에서 hover는 어두워지고(600→700), 다크에서는 밝아집니다(500→400). Primary 자체도 한 단계 밝은 blue.500을 씁니다 — 600은 다크 표면에서 침침합니다.

라이트
기본hoveractive
인터랙션 방향 — 라이트는 어두워지고, 다크는 밝아진다

② Primary 채움 위 잉크는 반전된다#

다크의 primary(blue.500) 위 백색 텍스트는 2.96:1로 읽기 어렵습니다. on-primary는 다크에서 gray.900(다크 잉크)으로 반전됩니다 — Material 다크 관례와 동일.

라이트

Primary 버튼

on-primary 반전 — 같은 토큰, 테마별 다른 잉크

③ 상태색은 -400 램프로 갈아탄다#

원색(500/600)은 다크 표면에서 대비가 부족합니다. 다크의 상태 표시·텍스트는 모두 -400 틴트를 사용합니다 (green-400 · amber-400 · red-400 · sky-400).

라이트
성공 success경고 warning오류 error정보 info
상태색 -400 전환 — 다크는 한 단계 밝은 틴트로 (점+라벨 이중 표현)

④ 그림자 대신 보더와 표면 위계#

다크에서 그림자는 거의 보이지 않습니다. 떠 있는 표면은 올라올수록 밝아져 위계를 만듭니다(M3 다크 규칙). surface-raised는 다크에서 neutral-tonal.t22surface(gray.800 ≈ 톤 16)보다 한 단계 밝은 톤으로, ADR-013 이전의 손으로 끼운 gray.750 중간 단계를 톤 수학 파생이 대체했습니다. 그림자 토큰은 두 테마 공통(core)으로 유지됩니다.

라이트

surface-raised 카드 — 같은 그림자, 다른 분리 단서

떠 있는 표면 — 라이트는 그림자로, 다크는 밝은 톤으로 분리

서피스 위계#

표면 토큰은 톤(neutral L*)이 올라가며 위계를 만듭니다. 다크는 라이트의 역방향 — 배경이 가장 어둡고, 올라온 표면일수록 밝습니다.

역할라이트다크다크 톤
bg (페이지)gray.50gray.900≈ t8
surface (콘텐츠)whitegray.800≈ t16
surface-raised (떠 있음)white + 그림자neutral-tonal.t22t22
surface-mutedgray.100gray.700≈ t27
surface-selectedblue.50blue.900
다크 표면 위계 — 같은 neutral 램프 위 톤 좌표
0
4
6
10
12
17
20
22
24
30
40
50
60
70
80
87
90
92
94
95
96
98
99
100
  • 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이라 어두운 표면을 밝히는 방향).

라이트
surfacehoverpressedraised
surface → hover → pressed — 같은 수식, 테마별 자동 방향

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 정책)

시멘틱 토큰 — 양 테마 값#

토큰라이트다크설명

Theme Architecture (예고)#

테마는 4계층으로 확장됩니다 — Foundation → WIZ Default → Customer → Enterprise. semantic 오버라이드 계층으로 실현하며(지금의 light/dark와 동일 메커니즘), MVP 범위 밖으로 구조만 보장합니다. 상세는 MASTER_PLAN §5-④.