53 lines
8.3 KiB
Markdown
53 lines
8.3 KiB
Markdown
# 디자인팀 컬러 Theme 사용 방법
|
|
|
|
Designer Playground는 내부 개발용 `internal` 태그로 기본 검수 메뉴에서 제외됩니다. 개발 서버 또는 배포 서버가 출력한 주소에 `?path=/story/theme-designer-playground--editor`를 붙여 직접 엽니다. 검수 화면은 HM Default를 사용합니다.
|
|
|
|
1. 처음 열면 `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**로 기본값을 다시 불러옵니다.
|
|
2. Primary / Active / Focus / Accent / Destructive 등 역할의 컬러 피커 또는 HEX 입력을 수정합니다. 불투명 6자리 HEX(`#123abc`)를 사용합니다. 유효한 값은 입력 즉시 적용되며 별도의 Apply 버튼이 필요 없습니다. 미완성 입력은 마지막 유효 색을 유지합니다.
|
|
3. 오른쪽 Live Preview에서 여러 컴포넌트를 함께 확인합니다. 화면이 좁으면 편집기 아래에 Preview가 이어집니다. Focus 확인은 Tab 키로 Checkbox/Input 등에 이동합니다. Select, Date Picker, Combobox 및 메뉴를 열면 Global Theme가 팝업에도 적용됩니다.
|
|
4. 임시 Theme는 Designer Playground 내부에만 적용됩니다. 다른 Component / Pattern Story로 이동하면 override를 해제하고 HM Default로 검수합니다. 편집기 내부 값 변경에는 reload, 파일 저장, Vite HMR, build, Storybook 재시작이 필요 없습니다.
|
|
5. **Reset to HM Default**는 현재 override를 해제하고 기본값을 즉시 복원합니다. 컴포넌트 API와 레이아웃은 바꾸지 않습니다.
|
|
6. **Show JSON**으로 현재 데이터를 표시하고 **Copy JSON**으로 복사하거나 **Export JSON**으로 `hm-color-theme.json`을 내려받습니다. 클립보드 접근이 막히면 JSON 입력란에서 직접 복사합니다. 수정한 키만 저장하므로 나머지는 HM Default입니다.
|
|
7. JSON을 입력란에 붙여 넣고 **Import JSON**을 누르거나 파일 입력으로 JSON을 선택하면 바로 적용됩니다. 이전 Theme와 병합하지 않고 새 Theme로 교체합니다. 잘못된 JSON/키/값/불완전한 gradient 그룹은 거부하고 마지막 유효 Theme를 유지합니다. 이 편집기는 컬러 전용이므로 radius 입력을 거부합니다.
|
|
8. 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](theme-delivery.md).
|
|
|
|
```ts
|
|
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는 83개 입력입니다(2026-10-11 기존 확정 브랜드 팔레트 8개 및 사용자 확정 Orange Dark 1·2 추가, 이전 81개 보존). 배포하는 Default JSON은 81개 컬러이며 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-theme-contract.md). Runtime 적용·제한: [Runtime Theme](runtime-theme.md).
|