fix(sw): 2026-10-21 SW design review and responsive header without More from 760px
User-approved design review (2026-10-21): - SW Header: from 760px up nothing moves into More; the five menus stay with their titles (titles and values ellipsize), file name shrinks to 96px. Open next to the logo no longer blocks field shrinking above 760px (760/768 overflow fixed, also for configured `controls` headers). Dropdown yellow ring inside the button, black seam. - Property Bar values as read-only red text; property popup "=" labels, read-only black values, per-entry hover with pointer. - Home Menu recent files (3 rows, path + name caption, empty preview), Footer + slot guide off by default, Viewer file list without icons, Storybook widths 1920-760. - Tests: old More expectations (integrated-improvement, keyboard-dismiss, footer-popup-viewer-refinement, storybook-cleanup-stage1) moved to the new rule; functional checks kept.
This commit is contained in:
1 parent
a25d2b31c5
commit
2fc1b3e108
37 files changed
+447
-211
No files matched your search
@@ -34,9 +34,10 @@ SW 공식 기준 Header(Figma 26:8944, 1920 × 49). 로고 · 파일 · 객체
|
||||
| 기타 | `activeMenu`, `disabled`(창 버튼 제외), `drawingModeLabel`, `tools?: ReactNode`(객체 영역 메뉴 뒤), `<header>` HTML 속성·`ref` |
|
||||
|
||||
- 데이터 배열(`layers`, `colors`, `lineTypes`/`lineWeights`, `textStyles`, `dimensionStyles`, `documents`)을 주지 않으면 해당 필드는 Dropdown 없는 버튼입니다.
|
||||
- 반응형(2026-10-21): Header 폭 760px 이상에서는 More로 옮기지 않습니다. 레이어·색상·선스타일·문자스타일·치수스타일 5개 메뉴와 타이틀은 항상 보이고, 좁아지면 그리기모드 텍스트·선/치수 그림 숨김 → 파일명 축소(최소 96px, `…`) → 메뉴 값 `…` 순으로 줄입니다. 1080px 미만(1024 등)은 아이콘·색상 칩·폰트명을 숨긴 텍스트만, 900px 이하는 선스타일 필드에서 가중치·스케일을 숨깁니다. 모든 값과 타이틀이 잘리지 않는 폭은 약 1,200px 이상입니다. 760px 미만은 기존 More 동작을 유지합니다.
|
||||
- 반응형(More·대표 필드 전환·창 영역 축소)은 **`SWHeader` 안에서만** 동작합니다(CSS container `hm-sw-header`). 조합형 구성이 반응형이어야 하면 `controls` + `documentOpenPlacement` + `leading` + `tools`로 `SWHeader` 안에서 구성합니다(예제 F).
|
||||
- 로고 옆 Open은 실제 공간을 측정해 넘칠 때만 More로 이동하고, 그 시점보다 Open 폭만큼 넓어지면 돌아옵니다. Open이 보이는 동안 파일명이 먼저 줄고 레이어 필드는 Figma 폭을 유지합니다.
|
||||
- 메뉴도 고정 폭만이 아니라 실제 남은 공간을 기준으로 More에 옮기고 공간이 생기면 원래 자리·순서로 돌려놓습니다(Breakpoint는 그대로, 추가 Prop 없음). 메뉴를 열고 닫아도 Header 요소의 위치·폭은 바뀌지 않습니다.
|
||||
- (760px 미만) 로고 옆 Open은 실제 공간을 측정해 넘칠 때만 More로 이동하고, 그 시점보다 Open 폭만큼 넓어지면 돌아옵니다. Open이 보이는 동안 파일명이 먼저 줄고 레이어 필드는 Figma 폭을 유지합니다.
|
||||
- (760px 미만) 메뉴도 고정 폭만이 아니라 실제 남은 공간을 기준으로 More에 옮기고 공간이 생기면 원래 자리·순서로 돌려놓습니다(Breakpoint는 그대로, 추가 Prop 없음). 메뉴를 열고 닫아도 Header 요소의 위치·폭은 바뀌지 않습니다.
|
||||
```tsx
|
||||
<SWHeader documentTitle={name} logoSrc={logo} logoAlt="제품명" layers={layers} activeLayerId={id} onLayerSelect={l => setId(l.id)} onClose={closeWindow} />
|
||||
```
|
||||
@@ -104,7 +105,7 @@ Figma 26:10591(home on), 타일 15종 26:11355 … 26:11631, 섹션 제목 26:12
|
||||
| `SWHomeMenu` | 2단 메뉴 전체(섹션 여러 개). 보통 `SWHeader homeMenu`로 씀 | `sections`(`SWHomeMenuSectionData[]`) 또는 `children`, `open`/`defaultOpen`(false)/`onOpenChange(open, reason)`, `activeIds`/`defaultActiveIds`/`onActiveChange`, `selection`(`multiple` 기본 / `single`), `onItemSelect`, `closeOnBackgroundClick`(true), `closeOnSelect`(false), `closeOnEscape`(true), `closeOnOutsideClick`(false), `autoFocus`(true), `returnFocusRef`, `accent`(`auto`/`sections`/`outline`), `moreLabel`("더보기") | 높이 77(섹션 75 + 강조 2), 섹션 폭은 타일 수로 자동. 좁으면 들어가는 섹션만 표시하고 나머지는 더보기(⋯) Dropdown의 텍스트 메뉴(섹션 제목 + 항목, 같은 Active·Callback·하위 패널)로 이동(가로 스크롤 없음, 넓어지면 복귀) | ✅ |
|
||||
| `SWHomeMenuSection` | 섹션(제목 badge + 타일 그룹) | `title`, `children` | badge 폭 = 글자 + 46px | ✅ |
|
||||
| `SWHomeMenuItem` | 80 × 46 타일(Default / Hover / Active) | 데이터 `SWHomeMenuItemData`: `id`, `label`, `icon`, `hoverIcon`, `toggle`(기본: `panel` 있는 항목만 true = 패널이 열린 동안 Active, 나머지는 실행 버튼 = 클릭 후 ON 없음. true = 켜고 끄기 유지), `panel`, `panelLabel`, `disabled`, `hidden`, `title`, `onSelect`. 메뉴 밖 단독이면 `active`/`defaultActive`/`onActiveChange` | Hover·Active = 주황 gradient 1px 테두리 + `#FF5C00` 아이콘·글자 | ✅ |
|
||||
| `SWRecentFiles` | 선택 하위 패널: 최근파일 목록 + 2뎁스 미리보기 | `files`(`SWFileEntry[]`: `id`, `name`, `path`, `badge`, `preview`, `previewTitle`, `disabled`), `onFileOpen`, `onFileHover`, `renderPreview`, `closeOnOpen`(true), `emptyText` | 폭 354, 행 50, 미리보기 310 × 270 | ✅ |
|
||||
| `SWRecentFiles` | 선택 하위 패널: 최근파일 목록(2026-10-21부터 앞 3개만 표시. Hover·Focus 시 2뎁스 미리보기 영역(제목 = 해당 파일의 `previewTitle` 또는 `name` + 검정 빈 본문)만 표시하고 `preview`·`renderPreview` 이미지는 호환용으로 받기만 하고 렌더링하지 않음) | `files`(`SWFileEntry[]`: `id`, `name`, `path`, `badge`, `preview`, `previewTitle`, `disabled`), `onFileOpen`, `onFileHover`, `renderPreview`, `closeOnOpen`(true), `emptyText` | 폭 354, 행 50, 미리보기 310 × 270 | ✅ |
|
||||
|
||||
- **Header 연결:** `SWHeader`의 `homeMenu`에 `SWHomeMenu` Props를 주면 됩니다. 기본 숨김, 로고 클릭 열기, 다시 클릭 닫기. 위치는 SWHeader가 실제 DOM으로 정합니다(객체 수정 영역 −2px ~ 창 영역, 고정 x 없음. `controls`에 `document`가 있으면 파일명 오른쪽 −2px부터). 로고·파일명·창 영역은 가리지 않습니다.
|
||||
- **이벤트 우선순위:** `homeMenu`가 있으면 로고 클릭은 메뉴 열기·닫기만 하고 `onHomeClick`을 호출하지 않습니다(의도하지 않은 홈 이동 방지). 상태 알림은 `onHomeMenuOpenChange`(`reason`: `home`, `escape`, `background`, `outside`, `select`, `file`, `document`).
|
||||
@@ -167,7 +168,7 @@ SW **뷰어 모드** 전용 Export입니다(2026-10-19 추가, 참고 DWG/DXF
|
||||
| `SWFooterAuxGroup` | 보조기능 토글 격자(Figma 3 × 2) | `items: SWFooterAuxItem[]`(필수), `onPressedChange`, `onItemClick`, `columns`(3), `label` | ◻ |
|
||||
| `SWFooterAuxButton` | 보조기능 104 × 33 버튼(Hover 노랑 테두리, `pressed` = 주황 테두리·아이콘·글자) | `label`(필수), `icon`(`currentColor` 아이콘이면 상태 색 적용), `pressed`, `button` 속성 | ◻ |
|
||||
| `SWFooterToolButton` | 명령 칸 68 × 47 | `label`(필수), `icon`, `activeIcon`, `pressed`, `button` 속성 | ◻ |
|
||||
| `SWFooterAddSlot` | 빈 칸(+), Hover 가이드 | `guide`(기본 Figma / `false`), `guideOpen`, `onGuideOpenChange`, `button` 속성 | ◻ |
|
||||
| `SWFooterAddSlot` | 빈 칸(+), Hover 가이드 | `guide`(기본 `false` = 없음, `{}` = Figma 가이드), `guideOpen`, `onGuideOpenChange`, `button` 속성 | ◻ |
|
||||
| `SWFooterGuide` | 빈 칸 안내 카드 208 × 149 | `title`(`명령어 등록`), `caption`(`빠른사용`), `media`, `div` 속성 | ◻ |
|
||||
| `SWFooterMenu` | 분류 행(현재 탭 Pocket, 넘치면 ◀ ▶) | `items: SWFooterMenuItem[]`·`value`(필수), `onValueChange`, `onAdd`, `addLabel`, `label`, `panelId`, `tabIdPrefix` | ◻ |
|
||||
| `SWFooterLayoutTabs` | 도면 공간 탭(+ · Layout · Model) | `layouts: SWFooterLayout[]`·`value`(필수), `onValueChange`, `onAdd`, `onRemove`, `onRename`, `editingId`/`onEditingChange`, `modelLabel`(`"Model"` / `false`), `label`, `addLabel`, `removeLabel` | ◻ |
|
||||
|
||||
@@ -82,7 +82,9 @@
|
||||
|
||||
## 7. 반응형 (`SWHeader` 전용)
|
||||
|
||||
Container `hm-sw-header` 기준 Breakpoint: **< 1800** 선/문자/치수스타일 → More, **< 1180** 그리기모드 숨김, **< 1080** 상세보기 → More·창 이동 24px(창 영역 176), **< 900** 색상 → More, **< 640** 인쇄·K → More·창 이동 숨김(창 영역 64), **< 520** 레이어 상태 아이콘 숨김. More에서 고른 필드는 첫 칸(레이어 자리)에 표시되고 Dropdown이 바로 열립니다(UI 상태만, 데이터 Callback 없음).
|
||||
**760px 이상(2026-10-21 사용자 결정):** More 없이 5개 메뉴(레이어·색상·선스타일·문자스타일·치수스타일)를 항상 Header에 둡니다. 로고 옆 Open 유무와 관계없이 넘치지 않으며, 좁아질수록 **< 1800** 그리기모드 글자·선/치수 그림 숨김·간격 축소 → 파일명 축소(최소 96px, `…`) → 정보값 `…` 순으로 공간을 줄입니다. 메뉴 타이틀은 모든 폭에서 표시하며 공간이 부족하면 `…`로 줄어듭니다. **< 1080** 레이어 상태 아이콘·색상 칩·글꼴 이름 숨김, **≤ 900** 선스타일은 선스타일 값만. Dropdown 열기·닫기는 그대로입니다. 아래 Breakpoint·실측 More는 **760px 미만**에만 적용됩니다.
|
||||
|
||||
760px 미만 Container `hm-sw-header` 기준 Breakpoint: **< 1800** 선/문자/치수스타일 → More, **< 1180** 그리기모드 숨김, **< 1080** 상세보기 → More·창 이동 24px(창 영역 176), **< 900** 색상 → More, **< 640** 인쇄·K → More·창 이동 숨김(창 영역 64), **< 520** 레이어 상태 아이콘 숨김. More에서 고른 필드는 첫 칸(레이어 자리)에 표시되고 Dropdown이 바로 열립니다(UI 상태만, 데이터 Callback 없음).
|
||||
|
||||
실측 More(2026-10-19): Breakpoint 위에서 객체 수정 영역의 실제 남은 공간을 측정해, `leading`·`tools`·긴 라벨 등으로 표시할 수 없는 메뉴만 같은 단계 순서(선/문자/치수 → 그리기모드 → 속성 블록 → 색상 → 구성형의 인쇄·K, 같은 단계는 오른쪽부터)로 More에 옮기고 공간이 생기면 역순으로 돌려놓습니다. 로고 옆 Open이 가장 먼저 옮겨집니다(좁아질 때). 넓어질 때(2026-10-20 수정안 A): Breakpoint로 막 돌아온 부분(인쇄·K, 색상, 속성 블록, 선/문자/치수, 그리기모드)은 실제 남은 공간이 있을 때만 돌아오고 없으면 More에 남으며, 다시 나타난 Open은 넓어지는 동안 다른 부분 때문에 More로 돌아가지 않습니다. 충분히 넓으면 모두 돌아옵니다. 메뉴 열기·닫기는 Header 요소의 위치·폭을 바꾸지 않습니다. 호스트 요소(`leading`·`tools`)는 More로 옮기지 않으므로 폭이 좁은 화면에는 많이 넣지 않습니다.
|
||||
|
||||
@@ -108,7 +110,9 @@ Container `hm-sw-header` 기준 Breakpoint: **< 1800** 선/문자/치수스타
|
||||
| 동작 | Non-modal(Dim·Portal·Focus trap 없음). Escape는 Popup 안이면 그 Popup, 밖이면 최근 사용 Popup 하나. `autoFocus`면 열릴 때 Focus, 안에서 닫히면 원래 위치로 | — |
|
||||
|
||||
- **Header 필드 Dropdown(`SWHeaderLayerMenu`·`SWHeaderColorMenu`·선/문자/치수 스타일)은 SWHeader 전용 디자인입니다.** Popup 안에 넣지 않습니다(2026-10-20 사용자 확정). Popup의 레이어·색상·선스타일은 속성창 컨트롤 `SWPopupPropertyRow`(속성창과 같은 `picker` 필드: 레이어 26:12250, 색상 26:12170, 선스타일 26:12388 — 값 `#E60403`, Hover 1px `rgba(33,29,19,.4)`, On `#211D13`, 목록은 고정 Overlay)를 씁니다. 그 밖의 행은 `SWPopupRow` + `SWHeaderInput`.
|
||||
- 선택 목록(단위 등)은 `SWSelect`입니다(native select, 28px · 좌우 8 · 1px `#948871` · radius 4 · 면 `#F1ECE1` · 12px 검정, 플랫폼 화살표·옵션 목록). 뷰어 축척 지정 팝업과 같은 모양이고 뷰어 패널 안에서는 `--hm-sw-viewer-panel-*` 값을 따릅니다. 토큰 `--hm-sw-select-border-color`·`-background`·`-text`.
|
||||
- 선택 목록(단위 등)은 `SWSelect`입니다(native select, 28px · 좌우 8 · 1px `#948871` · radius 4 · 면 `#F1ECE1` · 12px, 플랫폼 화살표·옵션 목록). 선택값은 변경 가능한 값이라 `#E60403`(2026-10-21), Disabled 값과 옵션 목록은 검정입니다. 뷰어 축척 지정 팝업과 같은 모양이고 뷰어 패널 안에서는 `--hm-sw-viewer-panel-*` 값(글자색 포함)을 따릅니다. 토큰 `--hm-sw-select-border-color`·`-background`·`-text`(Disabled 값·옵션 목록; Popup 안 선택값 빨강은 규칙으로 적용).
|
||||
- **속성값 색상(2026-10-21 사용자 확정):** 빨강 `#E60403`은 실제로 수정 가능한 값에만 씁니다. 밝은 속성창·Popup에서 수정할 수 없는 값(`readOnly`·`type: "computed"`·Disabled, Callback 없는 행)은 검정입니다. 어두운 속성Bar는 Bar에서 편집하지 않는 값을 포커스 없는 텍스트(`<output>`)로 보여 주며, 속성창에서 수정하는 값(원의 반지름·지름·원주·면적)은 빨강을 유지합니다. 클릭할 수 있다는 이유만으로 빨강을 쓰지 않습니다.
|
||||
- **속성창 입력(2026-10-21):** 숫자 값(선 가중치 포함)의 편집 Input은 값 영역 전체 너비를 채웁니다. 투명도는 값 + `annotation`(예 `(ByL)`)이 하나의 편집 상자이고 그 뒤에 게이지바·단위가 옵니다. 속성창 선꼴(`picker: "lineStyle"`) Dropdown은 선 종류 목록 1열(미리보기 + 이름)만 표시합니다. `menus.lineWeights`·`lineScale` 등은 속성창 Dropdown에 표시되지 않으며 SWHeader 선스타일 필드는 기존 3열을 유지합니다.
|
||||
- 게이지바는 `SWSlider`입니다. 모양 선택 우선순위: ① `appearance` Prop(명시) → ② 기본 `"panel"`. 테마 연동은 토큰 범위입니다: `panel` = `--hm-sw-slider-panel-track`(`#E0DACE`)·`-range`(`#266651`)·`-thumb`(`#FFFFFF`), `property` = `--hm-sw-property-range-fill`·`-fill-edge`·`-track`·`-highlight`(속성창과 같은 토큰). `SWTheme style`·Runtime 토큰 Override로 두 모양의 색이 함께 바뀌며, 테마 전체에서 기본 `appearance`를 바꾸는 설정은 없습니다. 새 색을 만들지 않습니다.
|
||||
- Popup 하단 버튼의 SW 디자인은 없습니다. 임의 색·크기로 만들지 말고 `@hm-design/ui` `Button` 등 기존 컴포넌트를 쓰거나 사용자에게 디자인을 확인합니다.
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ import "@hm-design/sw/styles.css"
|
||||
| `activeToolId` / `onToolSelect(toolId, categoryId, tool)` | `null` | 실행 중 명령 = 주황(Figma Variant3, `aria-pressed`) |
|
||||
| `slotCount` | `17` / `command`가 있으면 제한 없음 | 명령 + 빈 칸(+)의 최대 칸 수. **칸 영역의 폭은 바 폭으로만 정해지고 분류의 명령 수와 무관**합니다(분류를 바꿔도 칸 영역·명령창·명령어 전체보기·Layout 탭 위치가 그대로). 명령이 적으면 빈 칸, 많으면 마지막 칸의 ▲ 패널(§4.1) |
|
||||
| `onSlotAdd(slotIndex, categoryId)` | 없음 | 빈 칸 클릭(명령 등록). **없으면 빈 칸은 모양만 있고 반응하지 않음** |
|
||||
| `slotGuide` | Figma 가이드 | 빈 칸 Hover·키보드 Focus 시 위에 뜨는 208 × 149 안내 `{ title = "명령어 등록", caption = "빠른사용", media? }`. `media`는 194 × 111 영상·이미지(프로그램 제공). `false` = 없음 |
|
||||
| `slotGuide` | `false` | 빈 칸 Hover·키보드 Focus 시 위에 뜨는 208 × 149 안내(선택 사용). 2026-10-21부터 기본은 없음(+ 위 미리보기 제거). 필요할 때만 `{}`(Figma 가이드 `명령어 등록` / `빠른사용`) 또는 `{ title, caption, media }`를 전달. `media`는 194 × 111 영상·이미지(프로그램 제공) |
|
||||
| `onCategoryAdd` | 없음 | 분류 행 끝 + 버튼 표시 |
|
||||
| `auxItems` / `onAuxPressedChange(id, pressed)` / `onAuxItemClick(id)` | 없음 | 3 × 2 보조기능 토글(`SWFooterAuxItem`: `id, label, icon?, pressed?, title?, disabled?`). `pressed`를 주면 토글 |
|
||||
| `auxAll` / `commandAll` | 표시 | 양끝 74 × 71 버튼 `{ title, subtitle, tooltip, onClick, pressed, disabled }`. 기본 문구 `보조기능 / 전체보기`, `명령어 / 전체보기`. `false` = 숨김 |
|
||||
@@ -62,7 +62,7 @@ import "@hm-design/sw/styles.css"
|
||||
| `SWFooterAuxGroup` | 104 × 33 칸, gap 2 | `items`(필수), `onPressedChange`, `onItemClick`, `columns`(3), `label` |
|
||||
| `SWFooterAuxButton` | 104 × 33 | `label`(필수), `icon`, `pressed`, `button` 속성 |
|
||||
| `SWFooterToolButton` | 68 × 47 칸 | `label`(필수), `icon`, `activeIcon`, `pressed`, `button` 속성(`title` 생략 시 잘린 라벨만 자동 Tooltip). 연속 배치하면 칸 사이 1px 금색 구분선 |
|
||||
| `SWFooterAddSlot` | 68 × 47 칸(+ 68 × 46) | `guide`(기본 Figma 가이드 / `false`), `guideOpen`(Controlled), `onGuideOpenChange`, `button` 속성 |
|
||||
| `SWFooterAddSlot` | 68 × 47 칸(+ 68 × 46) | `guide`(기본 `false` = 없음 / `{}` Figma 가이드 / 내용 객체), `guideOpen`(Controlled), `onGuideOpenChange`, `button` 속성 |
|
||||
| `SWFooterGuide` | 208 × 149 | `title`, `caption`, `media`, `div` 속성. 단독 카드로 둘 때 `data-standalone=""` |
|
||||
| `SWFooterMenu` | 높이 24 | `items`(`{ id, label, disabled? }[]`, 필수), `value`(필수), `onValueChange`, `onAdd`, `addLabel`, `label`, `panelId`, `tabIdPrefix`. 현재 탭은 위 칸과 이어지는 Pocket 모양(SVG, 위치 자동 계산) |
|
||||
| `SWFooterLayoutTabs` | 높이 22 | `layouts`(`SWFooterLayout[]` = `{ id, label, locked?, shape? }`, 필수), `value`(layout id 또는 `SW_FOOTER_MODEL`), `onValueChange`, `onAdd`, `onRemove`, `onRename`, `editingId`/`onEditingChange`, `modelLabel`(`"Model"` / `false`), `label`, `addLabel`, `removeLabel` |
|
||||
@@ -79,7 +79,7 @@ import "@hm-design/sw/styles.css"
|
||||
|---|---|---|
|
||||
| 명령 | Default `#F6F4F2` / Variant2 Hover = Variant3 선택: `#FF5C00` + 주황 아이콘 | Hover는 CSS, 선택은 `activeToolId`·`pressed`. 아이콘·라벨 위치·크기와 칸 크기는 모든 상태에서 같음 |
|
||||
| 분류 탭 | Default `#D4CBBD` / Hover·현재 `#FF5C00`, 현재 탭은 Pocket | `categoryId`·`value` |
|
||||
| 빈 칸 | Default + / Hover 주황 점선 링 + 주황 + | Hover·Focus 시 `slotGuide` 표시 |
|
||||
| 빈 칸 | Default + / Hover 주황 점선 링 + 주황 + | `slotGuide`를 전달한 경우에만 Hover·Focus 시 안내 표시(기본 없음) |
|
||||
| Layout 탭 | Default 베이지 `#C3B79E` / Hover(선택 아님, ×) = Model과 같은 주황 그라데이션 면(글자는 Default와 동일: 검정 `#161410`, 크기·굵기·위치 불변) / On 갈색 그라데이션·흰 글자 / On hover / Variant5 이름 편집(`#0F0D0A`, 빨강 `#E60403`) / Variant6 편집 + Hover | `value`, 편집 = 더블클릭·F2 또는 `editingId` |
|
||||
| Model 탭 | Default 베이지 / Hover·On = 주황 그라데이션 면(`gra-border-orange`) + 검정 `#161410` 글자 | `value === SW_FOOTER_MODEL` |
|
||||
| `+` 버튼 | Layout 옆 `+` Hover = 같은 주황 그라데이션 면 + `+`. 분류 행 `+` Hover = `+` `#FF5C00` | `onAdd` / `onCategoryAdd` |
|
||||
|
||||
Reference in new issue
Block a user