docs(sw): Popup guidance, example comments, package README and link check

This commit is contained in:
shkim4 committed 2026-10-20 21:49:47 +09:00
1 parent 2ce24b8b43
commit e32a138f28
7 files changed
+92 -91

No files matched your search

+1 -1
View File
@@ -83,7 +83,7 @@ SW 패키지에는 Header·Popup 계열이 두 벌 있습니다. 화면마다 **
1. **먼저 검색한다.** §0에서 모드를 정하고, 요청 기능을 [COMPONENT_CATALOG.md](./COMPONENT_CATALOG.md)의 공개 컴포넌트(뷰어 모드는 §9와 [VIEWER.md](./VIEWER.md))에서 찾는다.
2. **있으면 재사용한다(1순위).** 뷰어 모드는 `SWViewerHeader`·`SWViewerMenu`·`SWViewerPanel`이다(VIEWER.md). 일반 모드에서 완성형 Header가 필요하면 `SWHeader` 하나만 쓴다. 기존 Props(`hiddenControls`, `menuOrder`, `controls`, `documentOpenPlacement`, `leading`, `tools`, 각 데이터 배열·Callback)로 해결되는지 먼저 본다. 팝업·설정창은 `SWPopup`, 버튼·탭·토글은 `SWToolButton` / `SWToolGroup`, 일반 모드 로고 클릭 2단 메뉴는 `SWHeader`의 `homeMenu`(`SWHomeMenu` 데이터, 최근파일은 `SWRecentFiles`)이다. `SWToolButton`과 `SWHomeMenuItem`은 역할이 다르다(도구 막대 버튼 / 메뉴 타일). 서로 대신 쓰지 않는다.
- Popup 요청은 이렇게 판단한다: ① `SWPopup`이 프레임(외형·닫기·Escape·스크롤)을 제공한다 → ② 내용은 `children`으로 자유 구성(구조 제한 없음) → ③ 행 모양은 `SWPopupSection` / `SWPopupRow` + `SWHeaderInput` → ④ SW에 없는 컨트롤은 `@hm-design/ui`를 children에 → ⑤ 프레임을 다시 만들거나 없는 Props(`content`, `renderContent` 등)를 추측하지 않는다.
- Popup 요청은 이렇게 판단한다: ① `SWPopup`이 프레임(외형·닫기·Escape·스크롤)을 제공한다 → ② 내용은 `children`으로 자유 구성(구조 제한 없음) → ③ 행 모양은 `SWPopupSection` / `SWPopupRow` + `SWHeaderInput`, 레이어·색상·선스타일 선택 행은 `SWPopupPropertyRow`(SWHeader 필드 Dropdown은 Header 전용), 게이지바는 `SWSlider`, 선택 목록은 `SWSelect` → ④ 그래도 SW에 없는 컨트롤(Switch, 하단 Button 등)만 `@hm-design/ui`를 children에 → ⑤ 프레임을 다시 만들거나 없는 Props(`content`, `renderContent` 등)를 추측하지 않는다.
3. **없으면 조합한다(2순위).** 개별 공개 컴포넌트(`SWHeaderHome`, `SWHeaderDocumentTitle`, `SWHeaderLayerMenu` …)를 `<SWTheme>` 안에 배치한다. 배치용 CSS만 소비 프로젝트에 작성한다([COMPOSITION_PATTERNS.md](./COMPOSITION_PATTERNS.md)).
4. **조합으로도 안 될 때만 새로 만든다(3순위).** 새 컴포넌트는 **소비 프로젝트**에 작성하고, 공개 컴포넌트(예: `SWHeaderInput`)를 내부에 재사용하며, 외형은 공개 토큰 `--hm-sw-header-*`만 읽는다([DESIGN_RULES.md](./DESIGN_RULES.md), 예제 D). 뷰어 모드의 새 UI는 `--hm-sw-viewer-*`(+ 공유 `--hm-sw-header-*` 면·외곽선, [DESIGN_RULES.md](./DESIGN_RULES.md) §11)를 읽고 Header 버튼·패널 버튼·입력은 `SWViewerHeaderButton`·`SWViewerButton`·`SWViewerField` + `SWViewerInput`을 재사용한다. 모드별 상세는 §0.4. 뷰어 화면에 일반 모드 컨트롤 모양을 섞지 않는다.
5. **토큰이 있는 값을 새로 만들지 않는다.** 크기·색·간격은 선택 모드의 토큰과 DESIGN_RULES(뷰어는 VIEWER.md도)의 확인값을 쓴다. 참고 값이 없을 때만 §0.4 ③으로 구성하고 "AI 구성 값 — 디자인 확인 필요"로 보고한다(화면 인상을 크게 바꾸는 값은 구현 전에 사용자에게 확인).
+2 -2
View File
@@ -73,12 +73,12 @@ SW 공식 기준 Header(Figma 26:8944, 1920 × 49). 로고 · 파일 · 객체
| `SWPopupSection` | 속성창 그룹 면(제목 + 내용) | `title`, `children`, `section` 속성 | 그룹 제목 700·70% 검정, 내용 면 `--hm-sw-property-content` | ✅ |
| `SWPopupRow` | 속성창 한 줄(라벨 + 값) | `label`(필수), `htmlFor`, `children`(값 컨트롤, SW 필드는 `SWHeaderInput`), `unit`, `field`(`box` 기본 · `compact` · `none`), `numeric`(숫자 편집 On), `readOnly`, `disabled` | 행 최소 32, 라벨 72, 값 상자 28(Default·Hover 테두리, 숫자 편집 시 #0F0D0A). `compact` = 41px hug 숫자 필드 | ✅ |
| `SWSlider` | 게이지바(native range, 2026-10-20). `SWPopupRow field="none"` 안이나 `SWTheme` 안 어디든 | `value`(필수), `min`(0)·`max`(100)·`step`(1), `onValueChange`(드래그·키보드마다), `onValueCommit`(값 확정 = native `change`), `appearance`(`"panel"` 기본 · `"property"`), `disabled`, `aria-label`, `input` 속성 | 모양만 다르고 값·이벤트·키보드는 같음. `panel` = 지금까지 Popup에서 쓰던 게이지바(6px 트랙 · 18px 흰 Thumb + 2px 녹색 테두리, `SWViewerSlider`와 같은 모양), `property` = 속성창 게이지바(베이지 트랙 · 빨강 채움 · Figma Thumb 14px). 폭은 행을 채움(호스트가 `style.width`로 지정 가능). Disabled 40% | ◻ |
| `SWPopupPropertyRow` | Popup 안 레이어·색상·선스타일 등 속성창 한 줄(2026-10-20) | `property`(`SWHeaderProperty`: `name`·`value`·`type`, 레이어는 `picker: "layer"` + `options`, 색상은 `type: "color"`), `menus`(`SWHeaderPropertyMenus`: `layers`·`colors`·…), `onPropertyChange(property, value)`, `className` | `SWHeaderPropertyPanel` 행과 같은 DOM·모양·동작(속성창 `picker`, 고정 Overlay 목록). **SWHeader 필드 Dropdown(`SWHeaderLayerMenu` 등)을 Popup에 넣지 않습니다** | ◻ |
| `SWPopupPropertyRow` | **Popup 안 레이어·색상·선스타일 선택 행의 공식 컴포넌트**(2026-10-20). 속성창 한 줄 | `property`(`SWHeaderProperty`: `name`·`value`·`type`. 레이어 = `type: "select"` + `picker: "layer"` + `options`, 색상 = `type: "color"`(picker 자동), 선스타일 = `type: "select"` + `linePreview: true` 또는 `picker: "lineStyle"`), `menus`(`SWHeaderPropertyMenus`: `layers`·`colors`·`lineTypes`·…), `onPropertyChange(property, value)`(선택한 행 id 또는 입력값, 호스트가 `property`를 갱신), `className` | `SWHeaderPropertyPanel` 행과 같은 DOM·모양·동작(속성창 `picker` 필드, 목록은 고정 Overlay라 스크롤 본문에 잘리지 않음). **SWHeader 필드 Dropdown(`SWHeaderLayerMenu` 등)을 Popup에 넣지 않습니다** | ◻ |
| `SWSelect` | 선택 목록(native select, 2026-10-20). `SWPopupRow field="none"`, `SWViewerField`, `SWTheme` 안 어디든 | `value`/`defaultValue`, `options`(`SWSelectOption[]` = `{ value, label?, disabled? }`) 또는 `<option>` children, `onValueChange(value)`, `disabled`, `id`·`aria-label`, `select` 속성 | 28px, 좌우 8, 1px `#948871`, radius 4, 면 `#F1ECE1`, 12px 검정, 플랫폼 화살표·옵션 목록. Popup 도면 설정 단위 = Viewer 축척 지정 단위. Disabled 40% | ◻ |
| `SWHeaderPropertyPanel` | 데이터 기반 속성창(2절). 같은 프레임이며 `children`도 받음 | 2절 | 같은 DOM·class | ✅ |
- **Escape·Focus:** Popup 안의 Escape는 그 Popup만 닫습니다. 바깥의 Escape는 가장 최근에 열리거나 사용한(Focus·클릭) Popup 하나만 닫습니다. Dropdown·편집 중인 Input처럼 Escape를 이미 처리한 요소(`preventDefault` / 전파 중단)가 있으면 Popup은 닫히지 않습니다.
- **Popup 안 SW Dropdown:** 레이어·색상·선·문자·치수 Dropdown은 Popup 안에서 고정 위치 Overlay로 열려 스크롤 본문에 잘리지 않습니다(아래에 자리가 없으면 위로 열림). 단, Header용 어두운 필드 모양 그대로이므로 밝은 Popup 면과 대비가 다릅니다. 속성창 행 모양의 선택 필드가 필요하면 `SWHeaderPropertyPanel`의 `picker` 속성(`properties`)을 씁니다.
- **Popup 안 선택 필드(2026-10-20 사용자 확정, [DESIGN_RULES.md](./DESIGN_RULES.md) §8):** Popup의 레이어·색상·선스타일은 `SWPopupPropertyRow`로 둡니다. SWHeader 필드 Dropdown(`SWHeaderLayerMenu`·`SWHeaderColorMenu`·`SWHeaderLineStyleMenu`·`SWHeaderTextStyleMenu`·`SWHeaderDimensionStyleMenu`)은 Header 전용 디자인이라 Popup에 넣지 않습니다(Popup 안에서도 열리기는 하지만 지원하는 조합이 아닙니다). 이름 목록에서 고르는 일반 선택은 `SWSelect`입니다. 문자·치수 스타일의 속성창 `picker`는 없으므로, Popup에 문자·치수 스타일 선택 행이 필요하면 새로 만들지 말고 부족한 API로 보고해 사용자에게 확인합니다.
- **Popup 하단 버튼(적용·취소)의 일반 모드 SW 전용 디자인은 아직 없습니다.** 자리는 `footer`(또는 `children`)이고 버튼은 소비 프로젝트 버튼이나 `@hm-design/ui`의 `Button`을 둡니다. 뷰어 전용 `SWViewerButton`을 일반 모드 Popup에 쓰지 않습니다. 어두운 `SWToolButton`을 밝은 Popup에 강제로 쓰지 않습니다.
## 4. 도구 막대 — 기존 SW 버튼 3종
@@ -1,6 +1,10 @@
// Example B — composition (2nd priority): a simplified viewer header
// Example B — composition (2nd priority): a simplified SW NORMAL-mode header (SWHeader parts, not SWViewer*)
// Logo → File → Layer → Color → K
// Only public components; the layout is the consumer's (example-layout.css) and <SWTheme> provides tokens.
// SW normal mode: individual SWHeader controls inside <SWTheme>. It is NOT the SW viewer mode — a viewer screen
// (DWG/DXF viewing) uses SWViewerHeader / SWViewerMenu / SWViewerPanel (Example H, VIEWER.md). "Viewer" in the file
// name, the function name and the sample labels (aria-label "뷰어 헤더", logoAlt "뷰어") is a former name of this
// sample product, kept so existing imports keep working.
import { useState } from "react"
import {
SWHeaderActions, SWHeaderColorMenu, SWHeaderDocumentTitle, SWHeaderHome, SWHeaderLayerMenu, SWTheme,
@@ -1,6 +1,10 @@
// Example F — a viewer header: logo → Open → file → layer → color → K, plus a tool bar (Model / Layout, 2.5D,
// Fit) after the menus. Everything is SWHeader props, so the existing responsive More serves the whole layout
// (Open moves into More when the measured header has no room). No freeze / lock, no "+ New" in this product.
// Example F — an SW NORMAL-mode SWHeader with file open and a tool bar: logo → Open → file → layer → color → K, plus
// a tool bar (Model / Layout, 2.5D, Fit) after the menus. Everything is SWHeader props, so the existing responsive
// More serves the whole layout (Open moves into More when the measured header has no room). No freeze / lock, no
// "+ New" in this product.
// It is NOT the SW viewer mode: a viewer screen (DWG/DXF viewing) uses SWViewerHeader / SWViewerMenu /
// SWViewerPanel (Example H, VIEWER.md). "Viewer" in the file and function name is a former name, kept so existing
// imports keep working.
import { useState } from "react"
import { SWHeader, SWToolButton, SWToolGroup } from "@hm-design/sw"
import { colors, documents, layers } from "./sample-data"