8.4 KiB
디자인팀 컬러 Theme 사용 방법
Designer Playground는 내부 개발용 internal 태그로 기본 검수 메뉴에서 제외됩니다. 개발 서버 또는 배포 서버가 출력한 주소에 ?path=/story/theme-designer-playground--editor를 붙여 직접 엽니다. 검수 화면은 HM Default를 사용합니다.
- 처음 열면
themes/default.json기반 HM Default 컬러가 표시됩니다. Load Default JSON, Load Service Example JSON으로 repository JSON을 URL에서 불러오거나 Theme JSON URL에 CDN URL을 입력한 뒤 Load URL을 누릅니다. 같은 탭에 저장값이 있다면 마지막 유효 Theme를 다시 표시합니다. 다른 Story로 이동해도 편집 데이터는 세션에 보관되지만 해당 Story의 색상은 HM Default이며, 편집기로 돌아오면 보관된 편집값을 다시 적용합니다. Reset to HM Default로 기본값을 다시 불러옵니다. - Primary / Active / Focus / Accent / Destructive 등 역할의 컬러 피커 또는 HEX 입력을 수정합니다. 불투명 6자리 HEX(
#123abc)를 사용합니다. 유효한 값은 입력 즉시 적용되며 별도의 Apply 버튼이 필요 없습니다. 미완성 입력은 마지막 유효 색을 유지합니다. - 오른쪽 Live Preview에서 여러 컴포넌트를 함께 확인합니다. 화면이 좁으면 편집기 아래에 Preview가 이어집니다. Focus 확인은 Tab 키로 Checkbox/Input 등에 이동합니다. Select, Date Picker, Combobox 및 메뉴를 열면 Global Theme가 팝업에도 적용됩니다.
- 임시 Theme는 Designer Playground 내부에만 적용됩니다. 다른 Component / Pattern Story로 이동하면 override를 해제하고 HM Default로 검수합니다. 편집기 내부 값 변경에는 reload, 파일 저장, Vite HMR, build, Storybook 재시작이 필요 없습니다.
- Reset to HM Default는 현재 override를 해제하고 기본값을 즉시 복원합니다. 컴포넌트 API와 레이아웃은 바꾸지 않습니다.
- Show JSON으로 현재 데이터를 표시하고 Copy JSON으로 복사하거나 Export JSON으로
hm-color-theme.json을 내려받습니다. 클립보드 접근이 막히면 JSON 입력란에서 직접 복사합니다. 수정한 키만 저장하므로 나머지는 HM Default입니다. - JSON을 입력란에 붙여 넣고 Import JSON을 누르거나 파일 입력으로 JSON을 선택하면 바로 적용됩니다. 이전 Theme와 병합하지 않고 새 Theme로 교체합니다. 잘못된 JSON/키/값/불완전한 gradient 그룹은 거부하고 마지막 유효 Theme를 유지합니다. 이 편집기는 컬러 전용이므로 radius 입력을 거부합니다.
- Export한 JSON을
themes/<서비스명>.json에 저장하고 검증·Git diff/review·commit/push 후 Theme artifact를 CDN에 별도 배포합니다. 개발팀은 설정한 Theme URL을loadRuntimeTheme에 전달하거나 API/로컬 JSON을applyRuntimeTheme에 전달하면 됩니다. 이미 지원하는 Theme JSON의 color-only 변경에는 UI package 재빌드·version up·재배포가 필요 없습니다. Component CSS 규칙이나 Runtime 계약 변경은 package 릴리스 경로를 따릅니다. 자세한 배포 절차: Theme delivery.
import "@hm-design/ui/theme.css"
import { applyRuntimeTheme, resetRuntimeTheme, isRuntimeTheme } from "@hm-design/ui/theme"
// 설정/API/사용자 입력에서 받아온 공식 v1 Theme JSON.
const theme = { schemaVersion: 1, tokens: { "color.state.active": "#007f73" } }
if (isRuntimeTheme(theme)) applyRuntimeTheme(document.documentElement, theme)
// 같은 root에 새로운 Theme를 전달하면 즉시 교체된다.
// isRuntimeTheme은 DOM을 건드리지 않는 사전 검증이다.
resetRuntimeTheme(document.documentElement)
컬러 역할과 적용 범위
- Primary는 Badge default, Pagination current, Button outline 및 내비게이션 강조 글자에 적용합니다. Brand Button/GNB의 gradient와 일부 palette 장식은 별도 기존 계약을 유지합니다. Primary 하나로 모든 gradient stop을 재설계하지 않습니다.
- Active는 Checkbox, Radio, Switch, Slider, Progress 및 Calendar/Date Picker의 선택 면을 바꿉니다. Focus와 독립적입니다. On Active는 그 위 아이콘/텍스트입니다.
- Focus는 일반 입력 테두리와 Checkbox/Calendar 등의 ring, Slider Keyboard Focus의 Focus Semantic 20% halo입니다. Slider Hover/Drag halo는 Primary 20%이며 GNB/LNB는 contextual navigation focus 예외를 유지합니다.
- Accent는 Select/메뉴 Item/Calendar range middle·hover/Pagination hover에 45%, Table 행 hover·selected에만 20%로 사용합니다. Combobox는 Command를 조합하므로 메뉴의 강조 역할을 사용합니다. Toggle/Toggle Group Selected, Menubar 상위 Highlighted/Open 및 Navigation Menu Trigger/Open은 Accent 100% + On Accent를 사용합니다. Navigation Current는 Primary + contextual surface로 Control Active와 구분합니다.
- Destructive는 오류, invalid 및 destructive 표현입니다. Primary/Active/Focus와 독립적입니다.
- 각 입력란은 Default JSON + partial override의 실제 계산된 역할 값을 표시합니다. Export는 표시값 전체가 아니라 명시적으로 수정·Import한 데이터를 저장합니다. Primary와 On Accent는 sibling Semantic이며 Default JSON과 CSS-only package fallback 모두 독립값을 유지합니다. 기본값이 같아도 Primary override가 On Accent를 함께 바꾸지는 않습니다.
저장과 알려진 제한
- 일반 새 탭은 독립 세션입니다. 탭 복제 또는 opener로 연 탭은 브라우저가 초기 sessionStorage를 복사할 수 있으며 이후 편집은 탭별로 독립적입니다.
- 서버/DB/Publish 기능은 없습니다. 같은 브라우저 탭의 Storybook preview origin에
sessionStorage로 보관하며, 세션 저장을 사용할 수 없는 환경에서도 현재 화면의 편집/Export는 동작합니다. 장기 보관은 JSON Export를 사용하세요. - Global Theme는
document.documentElement에 적용하며 body Portal도 같은 Theme를 사용합니다. wrapper 밖으로 Portal된 popup은 Scoped Theme를 자동 전달받지 않습니다. 이 제한은 기존 FOLLOW_UP입니다. - 전체 Runtime Contract는 84개 입력입니다(2026-10-11 기존 확정 브랜드 팔레트 8개 및 사용자 확정 Orange Dark 1·2 추가, 이전 81개 보존 및 Provisional Generic Status Error 1개 추가). 배포하는 Default JSON은 82개 컬러이며 radius/geometry는 package에서 관리합니다. 편집 화면은 상위 컬러 역할 17개만 노출하며 Component Token, radius, palette/gradient 개별 입력 UI를 만들지 않습니다. 기존 컬러 계약의 palette/gradient는 유효 JSON으로 Import할 수 있으며 gradient는 세트 전체를 제공해야 합니다.
- 명시적
[data-hm-theme]scope는 독립 HM preset이므로 Global Theme를 이어받지 않습니다. Production에서 같은 root는 한 owner가 Apply/Reset을 관리합니다. - Storybook 편집기 설치는 이번 코드 변경을 적용하는 최초 빌드가 필요합니다. 설치 후 컬러 값을 바꾸는 운영에는 재빌드가 필요 없습니다.
개발팀의 Default 유지보수
Default 컬러의 사람이 관리하는 원본은 themes/default.json입니다. contract.ts는 공개 key/property/type을 정의하고 Default literal을 중복 소유하지 않습니다. scripts/theme-templates/는 컬러 literal 없이 alias/geometry만 유지합니다.
Storybook의 src/theme/designer-preview.tsx는 themes/default.json을 직접 import합니다. 디자인팀이 default.json을 수정하면 개발 서버의 Storybook HMR로 기본값이 갱신됩니다. Preview는 이 Default와 partial override를 병합하며, Reset은 override를 비워 현재 Default를 확인합니다.
Theme-only 배포는 npm run build:themes로 독립 JSON artifact만 생성합니다. UI package의 fallback snapshot까지 새 버전에서 갱신할 때 npm run generate:theme-defaults로 primitives.css, default.css, default-values.generated.ts를 생성합니다. typecheck, build, build-storybook의 pre hook은 생성 결과의 일치를 검사합니다. 이미 배포한 UI package를 그대로 두고 CDN JSON만 바꿀 수 있습니다.
공식 전체 입력표: Runtime Theme Contract. Runtime 적용·제한: Runtime Theme.