feat: integrate latest HMDesign design system updates
This commit is contained in:
1 parent
99faec189e
commit
1c4e0bb9a1
209 files changed
+8845
-552
No files matched your search
+77
-9
@@ -2,7 +2,7 @@
|
||||
|
||||
현재 HM 구현의 기준 문서. 공통 원칙은 `docs/guidelines/프로젝트-지침.md`(§6, §7), Token 구조 원칙은 `테마-토큰-가이드.md`를 따른다. 이 문서는 Tabs 고유의 API·Token·상태·결정만 기록한다.
|
||||
|
||||
## 기본 사용: Primary (2026-10-08)
|
||||
## 기본 사용: Primary (2026-10-08 기본 API / 2026-10-09 조합 안내)
|
||||
|
||||
앱 진입점에서 `@hm-design/ui/theme.css`를 로드한다. `TabsList`의 기본값은 `fill=true`, `panelSurface="content"`이며 기본 API만으로 Primary가 적용된다.
|
||||
|
||||
@@ -14,23 +14,23 @@ import { Tabs, TabsList, TabsTrigger, TabsContent } from "@hm-design/ui"
|
||||
<TabsTrigger value="overview">개요</TabsTrigger>
|
||||
<TabsTrigger value="details">상세</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="overview" className="border bg-background rounded-b p-4">개요 콘텐츠</TabsContent>
|
||||
<TabsContent value="details" className="border bg-background rounded-b p-4">상세 콘텐츠</TabsContent>
|
||||
<TabsContent value="overview" className="px-0 py-6">개요 콘텐츠</TabsContent>
|
||||
<TabsContent value="details" className="px-0 py-6">상세 콘텐츠</TabsContent>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
- **Primary**: `<TabsList>`, `<TabsList fill>`, `<TabsList fill panelSurface="content">`는 같은 디자인이다. 선택 면은 White → `--hm-sem-bg-content` Gradient다.
|
||||
- **Secondary 명시적 사용**: 위 예제의 List를 `<TabsList fill panelSurface="surface" aria-label="업무 보기">`로 바꾸고 **각** `TabsContent`에 `border bg-card rounded-b p-4`를 사용한다. 선택 면은 기존 White surface다.
|
||||
- **Primary**: `<TabsList>`, `<TabsList fill>`, `<TabsList fill panelSurface="content">`는 같은 디자인이다. 실제 content 면 위에서 사용하며 선택 면은 White alpha **0.8** → `--hm-sem-bg-content` Gradient다. 탭 전체 opacity는 1이다.
|
||||
- **Secondary 명시적 사용**: 흰색 Card 안에서는 List를 `<TabsList fill panelSurface="surface" aria-label="업무 보기">`로 바꾸고 **각** `TabsContent`의 `px-0 py-6`를 유지한다. 바깥 Card가 White surface와 여백을 소유하므로 내부 패널에 별도 박스를 추가하지 않는다.
|
||||
- **Legacy non-fill 명시적 사용**: `<TabsList fill={false} aria-label="업무 보기">`와 **각** `TabsContent`의 `border bg-card rounded-b p-4` 조합으로 이전 스타일을 유지한다. `<TabsList fill={false} panelSurface="surface">`도 같은 시각이다. OLD_TEST_ONLY / REMOVE_CANDIDATE 이력은 유지하며 별도 승인 없이 삭제하지 않는다.
|
||||
|
||||
`TabsContent`는 패널 배경·테두리를 자동으로 지정하지 않는다. 소비자가 Primary에는 `bg-background`(content), Secondary / Legacy에는 `bg-card`(surface)를 연결한다. `panelSurface`는 List의 선택 면·연결 곡선에만 적용되며 콘텐츠 색을 바꾸지 않는다. Bar와 패널 사이에 gap이나 별도 구분선을 넣지 않는다. 상태·Variant는 §4.1, 외부 소비자 변경 안내는 §15를 따른다.
|
||||
`TabsContent`는 패널 배경·테두리를 자동으로 지정하지 않는다. Primary의 바탕은 페이지/Layout의 content 면(`bg-background`), Secondary는 상위 Card의 surface 면이다. `panelSurface`는 List의 선택 면·연결 곡선에만 적용되며 콘텐츠 색을 바꾸지 않는다. Bar와 패널 사이에 gap이나 별도 구분선을 넣지 않는다. 상태·Variant는 §4.1, 외부 소비자 변경 안내는 §15, 중첩 박스 없는 조합은 §16을 따른다. 2026-10-09 실제 구현 요청에 따라 Primary 상단 흰색 불투명도 80%를 해당 Tabs CSS Mapping에 반영했다(§16.3).
|
||||
|
||||
## 1. 상태
|
||||
|
||||
| 항목 | 내용 |
|
||||
|---|---|
|
||||
| 구현 상태 | 기본 Primary Fill + 명시적 Secondary Fill + Legacy non-fill + 넘침 이동 버튼(D-090) 구현 (`hm-tab` class 없음) |
|
||||
| 기준일 | 2026-10-08 (Primary 기본값 승인 반영) |
|
||||
| 기준일 | 2026-10-09 (D-01 조합·D-02 상단 White 80% 반영, API는 2026-10-08 기본값 유지) |
|
||||
| 기반 | shadcn/ui Tabs (Radix `Tabs`) |
|
||||
| 대표 Story | `Components/Navigation/Tabs` → `All` (이름 "Tabs"): Primary(Fill + content) / Secondary(Fill + surface) |
|
||||
| 보류 | 아래 §11 |
|
||||
@@ -77,7 +77,7 @@ import { Tabs, TabsList, TabsTrigger, TabsContent } from "@hm-design/ui"
|
||||
|
||||
### 4.1 현재 Fill 디자인: Primary / Secondary State · Variant
|
||||
|
||||
- **Primary (기본값)**: `fill=true`, `panelSurface="content"`. Selected는 White → bg-content Gradient, top / left / right는 Green Light 3(`--hm-tab-fill-line-color`), bottom은 content 패널색이다.
|
||||
- **Primary (기본값)**: `fill=true`, `panelSurface="content"`. Selected는 White alpha 0.8 → bg-content Gradient, top / left / right는 Green Light 3(`--hm-tab-fill-line-color`), bottom은 content 패널색이다. 전체 탭 opacity와 전경·경계는 변경하지 않는다.
|
||||
- **Secondary**: `fill=true`, `panelSurface="surface"`. Selected는 기존 White surface 면, 같은 Green Light 3 테두리, bottom은 surface 패널색이다.
|
||||
- **공통 Geometry**: 기존 높이 34px, Typography 16/24/700, 좌우 padding 16px, 상단 radius 4px, 선택 탭의 8px 곡선 연결을 유지한다. Overflow가 없으면 균등 폭, 모든 Fill 이웃은 1px left border와 `margin-left: -1px`로 경계를 공유한다. Overflow이면 라벨 필요 폭을 유지한다.
|
||||
- **Inactive**: 면·top / vertical border·전경은 §4의 기존 비선택 값, bottom line만 Green Light 3다.
|
||||
@@ -131,13 +131,15 @@ Radix Tabs 구조·ARIA(`role=tablist/tab/tabpanel`, `aria-selected`)·roving ta
|
||||
- `LongLabel`은 짧은 라벨, 긴 라벨 1개, 긴 라벨 여러 개, 260px 좁은 container를 함께 검증한다. 라벨은 `nowrap`·무말줄임이며 실제 필요 폭이 넘을 때 이동 버튼으로 전환한다.
|
||||
- non-fill Story(`Selected`, `SelectedMiddle`, `Fill`, `FillContent`, `FillOverflow`와 대표의 non-fill 구역)는 2026-10-06에 제거했다. API(`fill=false`, Legacy profile CSS)는 유지한다(§10).
|
||||
- 2026-10-08 숨김 `Compatibility`(`verification` 태그 + **VERIFICATION ONLY** 표시)는 Legacy `fill={false}` / `fill={false} panelSurface="surface"` 동일성과 `panelSurface="surface"`만 명시한 경우의 Secondary 전환을 확인한다. 일반 Story 메뉴를 추가하지 않는다.
|
||||
- Story의 콘텐츠 panel은 Primary `TabsContent` + `border bg-background`, Secondary / Legacy `TabsContent` + `border bg-card` 소비자 조합 예시다.
|
||||
- Overview / Default API / Variants / States 및 Fill verification 예제의 콘텐츠 panel은 `px-0 py-6`로 통일해 D-01을 실제로 반영한다. Primary는 상위 content 면, Secondary는 상위 surface 면에 연결하며 내부 패널의 별도 border·배경·radius를 제거한다. Compatibility의 Legacy non-fill 두 예제만 이전 `border bg-card rounded-b p-4`를 보존한다.
|
||||
- **Usage**(2026-10-09 추가)는 공개 Card / Input / Textarea / Table을 조합해 Card 내부 Secondary와 페이지 content 면 위 Primary를 보여준다. 두 예제 모두 `TabsContent`는 `px-0 py-6`이며 별도 배경·border·radius를 추가하지 않는다. 대표 Story ID·기존 구역·verification Story는 유지한다.
|
||||
|
||||
## 10. 사용자 확정 결정
|
||||
|
||||
- 2026-10-06: Tabs의 최종 디자인 언어는 **Primary = Fill + `panelSurface="content"`**(기본형), **Secondary = Fill + `panelSurface="surface"`**(서브형) 두 가지다. 이 결정이 ui_viz보다 우선한다. non-fill 기본 profile은 OLD_TEST_ONLY로 분류해 대표 Story에서 내렸다.
|
||||
- **2026-10-06 당시 범위**는 Storybook 대표형에 한정했다. 당시 Public API 기본값(`fill=false`, `panelSurface="surface"`)과 non-fill CSS branch는 유지하고 기본값 변경·branch 삭제를 별도 승인 대상으로 남겼다. 당시 저장소 내 소비처가 없다는 관찰은 외부 소비자의 무영향을 보장하지 않는다.
|
||||
- **2026-10-08 추가 개선 E 승인**: `TabsList` 기본값을 `fill=true`, `panelSurface="content"`로 변경한다. Primary / Secondary / Legacy의 기존 CSS 디자인 값·선택자·동작·Theme / Token을 유지한다. non-fill의 OLD_TEST_ONLY / REMOVE_CANDIDATE 이력과 명시적 사용 API는 유지하며 삭제 승인은 포함하지 않는다. `panelSurface`는 Fill일 때만 효과가 있는 List prop이다(`Tabs` Root prop이 아님).
|
||||
- **2026-10-09 실제 구현 요청**: 사전공유 D-01/D-02를 문서 외 실제 구현에도 적용한다. Fill Story의 중첩 패널 박스를 제거하고 PageHeader 대표 Pattern에 직접 Tabs를 조합한다. 기존 `tabs.css`의 `fill=true` + `panelSurface="content"` 내부 face gradient 상단만 80%로 바꾼다. Secondary·Legacy·공개 API·Theme JSON·공통 Palette 변경은 포함하지 않는다.
|
||||
|
||||
## 11. 미확정 / 보류
|
||||
|
||||
@@ -163,6 +165,7 @@ src/components/story-board.tsx
|
||||
|
||||
## 13. 검증 상태
|
||||
|
||||
- **2026-10-09 D-01/D-02 실제 반영**: 전체 typecheck·앱 build·Storybook build 통과. 1280×900 / 390×844의 Primary 선택 면 상단 `color(srgb 1 1 1 / 0.8)`·하단 불투명 content·전체 opacity 1, Secondary 불투명 White, Fill panel transparent/border 0/padding 24px 0을 확인했다. PageHeader Pattern의 8px·20px과 실제 조합, Legacy·Disabled·키보드·넘침 이동·긴 라벨·입력 초안 보존을 확인했다. 참고 원본/비대상 파일과 API는 보존했으며 상세 범위·수치는 §16의 통합 보고를 따른다. 아래 과거 검증 기록은 해당 날짜의 이력이다.
|
||||
- 2026-10-08 추가 개선 E: 기존 6024 Storybook 재사용. 대표 `All`에서 기본 Props / `fill`만 명시 / 두 Props 명시가 모두 Primary(`data-fill="true"`, `data-panel-surface="content"`)이며 같은 Gradient·Green Light 3 경계·34px·16/24/700·8px 곡선을 확인했다. Secondary의 White 면·패널과 Bar / panel 1px 겹침도 유지했다.
|
||||
- 숨김 `Compatibility`: `fill={false}`의 content / surface 조합은 같은 White 선택 면·Legacy 경계·라벨 필요 폭이고 곡선이 없다. `panelSurface="surface"`만 명시하면 Secondary다. CSS 주석을 제외한 모든 규칙·값과 Production의 기본값 두 개를 제외한 코드가 작업 시작 상태와 동일함을 비교했다.
|
||||
- 실제 포인터 / 키보드: 클릭·ArrowLeft / Right·Home / End 선택과 콘텐츠 전환, 비선택 Hover Black 20% / 선택 Gradient 유지, focus-visible 3px 링, Disabled opacity 0.5·pointer-events none·tabIndex -1·방향키 건너뛰기를 확인했다. 독립 Overflow Story는 260px frame / 192px list에서 다음 이동 `scrollLeft 0→33.33`, 이전 이동 `→0`, 끝 버튼 Disabled 전환과 선택 유지가 정상이다.
|
||||
@@ -216,3 +219,68 @@ src/components/story-board.tsx
|
||||
- **레이아웃 차이**: non-fill은 라벨 필요 폭, Fill은 Overflow가 없을 때 컨테이너 전체를 균등 분할한다. 높이 34px은 같으나 탭 폭·공유 경계·선택 연결 곡선·패널색이 달라질 수 있다. 좁은 폭에서는 기존 Overflow 이동 버튼이 나타날 수 있다.
|
||||
- **CSS Override 영향**: frame의 기본 attribute가 `data-fill="false"` / `data-panel-surface="surface"`에서 `"true"` / `"content"`로 바뀐다. non-fill 조건 selector, list width / flex, active background / border, 곡선 pseudo-element override를 사용하는 소비자는 검토가 필요하다. `className`과 ref는 계속 tablist에 전달된다.
|
||||
- **확인 범위**: 현재 저장소의 TabsList 사용은 Story만 확인했다. 외부 소비자 전체의 명시적 Props·패널색·레이아웃·CSS Override는 실제 확인하지 못했으므로 위 내용은 영향 가능성과 이행 안내이며 외부 호환성 전체 검증을 뜻하지 않는다.
|
||||
|
||||
## 16. Publisher / Developer 조합 안내 (2026-10-09)
|
||||
|
||||
사전공유 v0.2의 D-01(중첩 박스 제거)을 기존 공개 API로 표현한다. Component 자체에는 원래 패널 박스가 없으므로 소비 조합만 바꾸며 새 Variant·Token을 만들지 않는다.
|
||||
|
||||
### 16.1 표면 선택과 여백 소유권
|
||||
|
||||
| 상황 | List | 콘텐츠 배치 |
|
||||
|---|---|---|
|
||||
| 기본 흰색 Card 안 | `panelSurface="surface"` | Card / CardContent의 기본 여백을 유지. 각 TabsContent는 `px-0 py-6` |
|
||||
| Card 없이 content 페이지 위 | 기본 List 또는 `panelSurface="content"` | 기존 Layout의 content 배경·여백 사용. 탭 전체를 새 흰색 박스로 감싸지 않음 |
|
||||
| 기존 `Card surface="content"` 안 | `panelSurface="content"` | 실제 하단 표면에 맞춤. 흰색 Card 예제를 기계적으로 적용하지 않음 |
|
||||
| 내부 정보 구분 필요 | 실제 하단 표면에 맞춤 | 기존 Separator / Alert 등 역할이 있는 Component를 조합 |
|
||||
|
||||
```tsx
|
||||
import { Card, CardContent, CardHeader, CardTitle, Tabs, TabsContent, TabsList, TabsTrigger } from "@hm-design/ui"
|
||||
|
||||
<Card className="min-w-0">
|
||||
<CardHeader><CardTitle>프로젝트 정보</CardTitle></CardHeader>
|
||||
<CardContent className="min-w-0">
|
||||
<Tabs defaultValue="overview">
|
||||
<TabsList panelSurface="surface" aria-label="프로젝트 정보 보기">
|
||||
<TabsTrigger value="overview">기본 정보</TabsTrigger>
|
||||
<TabsTrigger value="schedule">일정·산출물</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="overview" className="px-0 py-6">기본 정보</TabsContent>
|
||||
<TabsContent value="schedule" className="px-0 py-6">일정·산출물</TabsContent>
|
||||
</Tabs>
|
||||
</CardContent>
|
||||
</Card>
|
||||
```
|
||||
|
||||
- **Do**: 바깥 Card의 배경·border·radius·24px 기본 여백을 유지하고 중복 `rounded-b border bg-background p-6`만 제거한다. 콘텐츠 내부 Input·Textarea·Table의 고유 스타일은 유지한다.
|
||||
- **Don't**: Input border, Table 행 배경, Alert 표면까지 일괄 제거하지 않는다. `panelSurface`만 바꾸고 실제 상위 배경은 다른 색으로 두지 않는다.
|
||||
- `py-6`(현재 24px) / `px-0`은 이 탭 조합의 예시 값이다. 모든 Component의 padding이나 제목→설명 간격으로 승격하지 않는다. [Card](card.md#3-기본-규격)의 Header→Content 24px과 [PageHeader](../patterns/page-header.md#3-token-packagesuisrcthemepage-headercss)의 제목→설명 8px·아래 콘텐츠 20px은 별개다.
|
||||
- CardDescription은 PageHeaderDescription과 동일 규격이 아니다. [CardDescription의 shadcn 호환 범위](card.md#51-carddescription-사용-범위)를 따른다.
|
||||
|
||||
### 16.2 Responsive / Accessibility / 상태 확인
|
||||
|
||||
- 소비 Layout의 flex/grid 자식인 **Card 자체**와 CardContent·Tabs는 필요 시 `min-w-0`으로 수축을 허용한다. CardContent에만 지정하면 grid 자식 Card의 min-content 폭(내부 Table 최소 폭 + 좌우 padding)이 페이지를 넓힐 수 있다. 긴 라벨은 말줄임으로 대체하지 않고 기존 Tabs 넘침 이동을 사용한다. Table의 기본 최소 폭 520px과 내부 스크롤은 [Table](table.md)을 유지한다.
|
||||
- `aria-label` 또는 `aria-labelledby`로 tablist를 식별하고 Trigger / Content의 `value`를 일치시킨다. Input·Textarea에는 연결된 Label을 둔다. 입력 상태를 탭 전환 후에도 유지해야 하면 소비자 상위 state로 관리한다(Usage 예제 참고).
|
||||
- 클릭, ArrowLeft/Right, Home/End, focus-visible, disabled 건너뛰기, 넘침 버튼과 선택 콘텐츠 전환을 확인한다. Disabled trigger 전체 opacity 0.5는 기존 상태 계약이며 아래 그라데이션 alpha와 별개다.
|
||||
- Empty / Loading / Error 표현이 필요하면 기존 Component / Pattern을 조합한다. 패널 박스 제거는 데이터 조회·오류 처리나 새로운 Tabs 상태 API를 제공하지 않는다.
|
||||
- desktop / mobile에서 문서 전체 가로 넘침과 내부 Tabs / Table 스크롤을 구분한다. utility 이름만 확인하지 말고 실제 패널 배경 transparent·border 0·padding 24px 0 및 자식 정렬을 브라우저에서 확인한다. 공통 검증은 [개발 적용 가이드](../guidelines/개발-적용-가이드.md#81-탭-조합과-역할별-간격)를 따른다.
|
||||
|
||||
### 16.3 D-02: 상단 흰색 80% 실제 반영
|
||||
|
||||
사전공유 폴더의 원문은 v0.2 상태를 유지하지만, 사용자가 2026-10-09 후속 요청에서 보류 항목을 실제 구현까지 반영하도록 명시했다. 이 요청에 따라 공통 Theme 전체가 아니라 **Tabs의 Primary content branch만** 아래와 같이 적용했다.
|
||||
|
||||
```css
|
||||
[data-slot="tabs-frame"][data-fill="true"][data-panel-surface="content"] {
|
||||
--hm-tab-fill-panel: var(--hm-sem-bg-content);
|
||||
--hm-tab-fill-face: linear-gradient(
|
||||
to bottom,
|
||||
color-mix(in srgb, var(--hm-sem-palette-white) 80%, transparent) 0%,
|
||||
var(--hm-sem-bg-content) 100%
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
실제 출력 대상은 Fill의 `[data-slot="tabs-trigger"][data-state="active"]`가 소비하는 `background-image`다. 면의 상단 흰색 alpha만 0.8이고 하단 content는 불투명이다. 방향·stop 위치·텍스트·아이콘·경계·Secondary·Legacy·비선택 Hover·Focus·Disabled 상태 규칙을 유지하며 탭 전체 `opacity`는 1이다(기존 Disabled opacity 0.5는 유지). 새 공개 Theme JSON alpha 입력이나 Component API를 추가하지 않았다.
|
||||
|
||||
현재 저장소의 TabsList 소비처는 Tabs 대표/verification Story와 PageHeader 대표 Pattern 조합이다. 이 content branch를 사용하는 외부 앱도 패키지 CSS 업데이트 시 새 면을 받지만 외부 코드와 override 전체는 제공되지 않아 별도 확인 대상이다. 같은 Default 흰색을 사용하는 Button·Card·Input·다른 Pattern에는 변경이 전파되지 않는다.
|
||||
|
||||
비교 분류·반영 범위와 이번 검증은 [사전공유 통합 보고](../guidelines/publisher-integration-2026-10-09.md)를 따른다. 외부 소비 화면과 참고 예시의 모바일 이슈는 소스가 제공되지 않아 추가 확인 대상이다.
|
||||
Reference in new issue
Block a user