From e32a138f287df4b01d264696bff4f04f43977536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=88=98=ED=98=84?= Date: Tue, 20 Oct 2026 21:49:47 +0900 Subject: [PATCH] docs(sw): Popup guidance, example comments, package README and link check --- docs/sw/sw-pc-handoff-2026-10-20.md | 14 +- packages/sw/README.md | 143 ++++++++---------- packages/sw/ai/AI_USAGE.md | 2 +- packages/sw/ai/COMPONENT_CATALOG.md | 4 +- .../sw/ai/examples/ExampleB-ViewerHeader.tsx | 6 +- .../sw/ai/examples/ExampleF-ViewerToolbar.tsx | 10 +- packages/sw/tests/ai-docs.check.mjs | 4 + 7 files changed, 92 insertions(+), 91 deletions(-) diff --git a/docs/sw/sw-pc-handoff-2026-10-20.md b/docs/sw/sw-pc-handoff-2026-10-20.md index f0463f4..2a60964 100644 --- a/docs/sw/sw-pc-handoff-2026-10-20.md +++ b/docs/sw/sw-pc-handoff-2026-10-20.md @@ -20,11 +20,19 @@ npm run check:ai-docs ### 브라우저 테스트 (`packages/sw/tests/*.browser.mjs`) -Playwright는 저장소 의존성이 아닙니다. 기존 PC는 저장소 밖 런타임(`C:/Users/user/.cache/codex-runtimes/.../node_modules`)을 기본값으로 씁니다. 새 PC에서는 환경 변수로 지정합니다. +Playwright는 저장소 의존성이 아닙니다. 모든 브라우저 테스트는 공통 모듈 `packages/sw/tests/playwright-runtime.mjs`로 Playwright(및 `pngjs`·`pixelmatch`)를 찾습니다(2026-10-20, PC별 절대경로 기본값 제거). 찾는 순서: + +1. `SW_PLAYWRIGHT_PATH` — playwright 패키지 폴더(또는 진입 파일) +2. `SW_RUNTIME_MODULES` — `playwright`가 설치된 `node_modules` 경로 (예: 별도 폴더에서 `npm i playwright` 후 그 `node_modules`) +3. `HM_PLAYWRIGHT_DIR` — `node_modules/playwright`를 가진 프로젝트 폴더(`scripts/verify-quality-runtime.mjs`와 같은 변수) +4. 저장소의 `node_modules/playwright` +5. 사용자 홈의 Codex 런타임 `~/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules`(사용자 이름과 무관) +6. 전역 npm(`npm root -g`) + +환경 변수로 지정한 경로에 Playwright가 없으면 다른 위치로 넘어가지 않고 시도한 위치를 보여 주며 실패합니다. -- `SW_RUNTIME_MODULES` — `playwright`가 설치된 `node_modules` 경로 (예: 별도 폴더에서 `npm i playwright` 후 그 `node_modules`) - `SW_CHROME_PATH` — Chrome 실행 파일(기본 `C:/Program Files/Google/Chrome/Application/chrome.exe`) -- Firefox 테스트는 설치된 Firefox를 WebDriver BiDi로 사용 +- Firefox 테스트는 설치된 Firefox(`SW_FIREFOX_PATH`)를 WebDriver BiDi로 사용하며 전역 `WebSocket`이 필요합니다: Node 22 이상, 또는 Node 20에서는 `node --experimental-websocket ` - 실행 전 `npm run build-storybook`(일부 테스트는 `npm run storybook`의 6024 포트) 필요 ## 2. 현재 상태와 남은 문제 diff --git a/packages/sw/README.md b/packages/sw/README.md index 3738cf8..4e81dc4 100644 --- a/packages/sw/README.md +++ b/packages/sw/README.md @@ -1,104 +1,85 @@ # @hm-design/sw -> **0.2.0 통합 개선(2026-10-19):** 패키지에 포함된 AI 안내 [ai/AI_USAGE.md](./ai/AI_USAGE.md)·[카탈로그](./ai/COMPONENT_CATALOG.md)가 공개 API의 기준입니다. 추가: `SWPopup` / `SWPopupSection` / `SWPopupRow`(속성창 외형 + `children` 자유 콘텐츠, 여러 Popup Escape 스택, Popup 안 Dropdown 고정 Overlay), `SWHeaderPropertyPanel`의 `children`·`title`·`autoFocus`와 선택형 `selection`/`properties`/`groups`, `SWToolButton` / `SWToolGroup`(기존 글자 토글·pill·파일명 면 재사용), `SWHeader`의 `documentOpenPlacement`(로고 오른쪽 Open, 실측 기반 More 이동)·`leading`, `hiddenControls`의 `documentNew`·`documentOpen`·`layerFreeze`·`layerLock`, `showNew`/`showOpen`/`showFreeze`/`showLock`. 모두 선택 Props이며 기존 화면은 그대로입니다. 빌드는 줄바꿈 정규화로 재현 가능하고 `dist/build-info.json`에 출처 Commit·도구 버전을 남깁니다. 검증 기록: 저장소 `docs/sw/sw-integrated-improvement-2026-10-19.md`. -> -> **2026-10-20:** `SWSlider` 추가(게이지바, `appearance` `"panel"` 기본 / `"property"` 속성창 모양, 값·이벤트 공통). `SWSelect`(native 선택 목록, Popup·Viewer 공통), `SWPopupPropertyRow`(Popup 안 레이어·색상 = 속성창 picker, SWHeader 필드 Dropdown은 Header 전용) 추가. SWHeader 넓어질 때 More 복귀 히스테리시스 수정(Open 재이동 없음). Footer Model·Layout 탭 주황 그라데이션·전체보기 Hover, 선택 분류 Pocket 면 통일. 뷰어 패널 312px 미만 폭의 제목 배경 누락 수정. 기록: 저장소 `docs/sw/sw-footer-popup-viewer-refinement-2026-10-20.md`. +HM Design System의 SW(설치형·도면 SW) 전용 React 컴포넌트 패키지입니다(0.2.0). `@hm-design/ui`와 독립적으로 빌드·배포·사용하며 서로 의존하지 않습니다. 공개 API의 기준은 패키지에 포함된 [ai/COMPONENT_CATALOG.md](./ai/COMPONENT_CATALOG.md)와 `dist/index.d.ts`입니다. 이 README는 요약입니다. -> **로고 클릭 메뉴(2026-10-19):** `SWHomeMenu` / `SWHomeMenuSection` / `SWHomeMenuItem` / `SWRecentFiles`(Figma 26:10591 2단 Header 메뉴, 최근파일 하위 패널)와 `SWHeader`의 `homeMenu`·`homeMenuOpen`·`defaultHomeMenuOpen`·`onHomeMenuOpenChange`. 기본 숨김 → 로고 클릭 열기 → 다시 클릭 닫기, 위치는 Header DOM 측정. `homeMenu`가 있으면 로고 클릭은 `onHomeClick`을 호출하지 않습니다. 모두 선택 Props이며 주지 않으면 기존 화면 그대로입니다([카탈로그 5절](./ai/COMPONENT_CATALOG.md), [예제 G](./ai/examples/ExampleG-HomeMenu.tsx)). 검증 기록: 저장소 `docs/sw/sw-home-menu-integration-2026-10-19.md`. - -> **현재 기준 색인(2026-10-19 1차 정리):** 아래 날짜별 안내는 작성 당시 기록입니다. 현재 기준은 [사용 가이드](../../docs/sw/sw-header-usage.md), [디자인 명세](../../docs/sw/sw-header-design-spec.md) 상단 색인, 속성 필드 13개 [검증 기록](../../docs/sw/sw-property-fields-verification-2026-10-19.md), 게이지·속성Bar [후속 4건 기록](../../docs/sw/sw-header-followup-four-design-fixes-verification-2026-10-19.md)·[Firefox 게이지 기록](../../docs/sw/sw-header-firefox-range-close-verification-2026-10-19.md)입니다. Storybook은 `SW / Header` 33개 Story이며 전체 목록과 2차 검토 대상은 [1차 정리 보고](../../docs/sw/sw-first-pass-cleanup-review-2026-10-19.md)에 있습니다. - -> **3차 구현(2026-10-16):** `hiddenControls`(로고 외 모든 구성요소 개별 제거, 로고 필수), `menuOrder`(레이어·색상·선/문자/치수스타일 순서), 속성창 `shapeContent` Slot, 속성창 4상태 개별·비교 Story를 추가했습니다. 미지정 시 기존 디자인과 같습니다. [사용법](../../docs/sw/sw-header-usage.md#구성요소-표시메뉴-순서속성창-4상태형상-slot-2026-10-16-3차), [3차 검증 기록](../../docs/sw/sw-header-composition-shape-verification-2026-10-16.md). - -> **후속 구현(2026-10-16):** 속성Bar(`SWHeaderPropertyBar`), 메뉴 단위 `controls` allowlist, Colorize 원본 Default/Hover를 추가했습니다. 상세 pill의 미사용 Stroke 선언·변수는 원본에서 제거했습니다. [사용법](../../docs/sw/sw-header-usage.md#후속-5개-요구사항-연결-2026-10-16), [새 검증 기록](../../docs/sw/sw-header-followup-five-verification-2026-10-16.md)을 따릅니다. 이전 설명과 PASS 로그는 보존합니다. - -> **최신 추가 구현(2026-10-16):** 상세 5개 Hover·색상 기준 필수 선택·목록 Hover/Selected 통일·데이터 기반 속성창·K 가이드 반복을 제공합니다. 아래 추가 연결과 [현재 검증 보고](../../docs/sw/sw-header-additional-verification-2026-10-16.md)를 따릅니다. 아래의 이전 Hover 없음·일반 자기 색 Stroke 설명은 추가 기준으로 대체됩니다. - -HM Design System의 SW(설치형·도면 SW) 전용 React 컴포넌트 패키지입니다. `@hm-design/ui`와 독립적으로 빌드·배포·사용하며 서로 의존하지 않습니다. - -현재 포함: **SW Header** (Figma `rj6wpsfk24lOWvWiVRAANP` node `26:8944` `header_green`), `SWTheme`. +## 설치·Import ```tsx import { SWHeader } from "@hm-design/sw" -import "@hm-design/sw/styles.css" +import "@hm-design/sw/styles.css" // 앱 진입점에서 한 번 ``` -- 로고는 확정 디자인이 아닙니다. 로고 영역 배치는 공통이고 로고 이미지는 각 SW 프로그램이 `logoSrc` 또는 `logo`로 전달합니다. 패키지에는 로고가 없으며, 전달하지 않으면 로고 없이 표시됩니다. +- 진입점은 `@hm-design/sw`(JS·타입)와 `@hm-design/sw/styles.css` 두 개뿐입니다. `dist/components/...` 같은 내부 경로는 공개 API가 아닙니다. +- Peer: `react`, `react-dom` `^19.0.0`. 런타임 dependency는 없고, SVG·PNG 자산은 JS에 data URI로 포함됩니다. CSS는 자동 import되지 않으며 전역 선택자(`html`, `body`, `*`)를 쓰지 않습니다. +- Registry에는 아직 게시하지 않았습니다. 소비 프로젝트는 HMDesign 저장소를 Git Submodule + npm Workspace로 연결하거나 `npm pack`으로 만든 tarball을 설치합니다. +- 패키지 내용: `dist/`(`index.js`·`index.d.ts`·`styles.css`·`build-info.json` — 출처 Commit·도구 버전), `ai/`(AI 코딩 도구용 안내·예제), `README.md`, `package.json`. -- 파일명을 클릭하면 문서 Dropdown(Figma 26:10662)이 열립니다. 목록은 `documents`, 선택·New·Open은 Callback으로 각 프로그램이 연결합니다(`documents` 미전달 시 Dropdown 없음). -- 레이어 필드를 클릭하면 레이어 Dropdown(Figma 26:10940, 갈색 목록·주황 행 Hover)이 열립니다. 목록은 `layers`(`id`, `name`, `color`, `visible`, `frozen`, `locked`, `disabled`), 현재 레이어는 `activeLayerId`이며 선택은 `onLayerSelect`, 전구·눈꽃·자물쇠는 `onLayerVisibilityChange` / `onLayerFreezeChange` / `onLayerLockChange`, 하단 버튼은 `onLayerDetail`로 각 프로그램이 연결합니다. 아이콘은 데이터만 반영하며 실제 표시·동결·잠금은 호스트가 처리합니다(`layers` 미전달 시 기존 필드 버튼). 확정 매핑: 전구 컬러 `visible=true`·회색 `false`, 눈꽃 컬러 `frozen=false`·회색 `true`, 자물쇠 컬러 `locked=false`·회색 `true`이며 클릭 시 각 boolean의 반전값을 전달합니다([명세 §5.2](../../docs/sw/sw-header-design-spec.md#52-레이어-dropdown-figma-headermenu레이어-2610940-2026-10-16), [검증 기록](../../docs/sw/sw-header-layer-dropdown-verification-2026-10-16.md)). -- Hover는 Figma 홈 버튼의 노란 gradient 1px 테두리를 SW Header의 테두리 있는 버튼에 공통 적용합니다(디자인 명세 §11.1). -- 창 이동 Hover Motion은 GIF의 경로를 유지하고 후속 사용자 요청으로 1.64 → **1.4초**로 단축했습니다. 커서 상승 → 약 444ms 문구 등장 → 오른쪽 위로 이동 → 약 888ms부터 512ms 유지 → 반복입니다. 기존 SVG·줄무늬·Tooltip·`onWindowMoveStart`·Drag 중 정지·Reduced Motion·88px/24px/숨김 정책은 유지합니다. 실제 창 이동은 호스트 책임이며 [사용 가이드 §10.2](../../docs/sw/sw-header-usage.md#102-창-이동-hover-motion), [현재 검증 기록](../../docs/sw/sw-header-speed-composed-hover-verification-2026-10-16.md)을 따릅니다. -- 그룹 필드 Hover는 텍스트와 선/폰트/치수 미리보기를 `#FFC600`으로 표시합니다. 기존 Gradient Border·검정 외곽선·색상 견본·레이어 상태·Disabled/Selected 정책을 유지하며 상세보기는 기존 텍스트 전용 Hover 그대로입니다([명세 §11.5](../../docs/sw/sw-header-design-spec.md#115-현재-추가-기준--1400ms-및-그룹-필드-hover-2026-10-16)). -- 색상·선스타일·문자스타일·치수스타일 Dropdown(2026-10-16, Figma 26:10986 / 26:11036 / 26:12666 / 26:12659 / 26:11104 / 26:10702 / 26:11181 / 26:11215): `colors`·`userColors`·`colorMode`, `lineTypes`·`lineWeights`, `textStyles`, `dimensionStyles`를 주면 각 필드가 Dropdown이 됩니다(주지 않으면 기존 버튼). 모든 항목은 `id` 기반 배열 Props이며 추가·삭제·이름/값 변경·재정렬에 소스 수정이 필요 없습니다. 선택·입력은 `onColorSelect` / `onColorModeChange` / `onColorInput` / `onColorPick`, `onLineTypeSelect` / `onLineWeightSelect` / `onLineWeightValueChange` / `onLineScaleChange`, `onTextStyleSelect`, `onDimensionStyleSelect`, 하단 `… 상세`는 `on*Detail`로 각 프로그램이 연결합니다(상세 팝업은 미제공). Dropdown 안 독립 버튼은 Hover 효과가 없고 목록 행·Input은 Figma Hover를 유지합니다(이후 2026-10-16 추가 수정: ByLayer/ByBlock·`… 상세` 버튼은 Figma Hover 적용, 색상 추출은 Colorize Hover, 색상 칩은 Hover 없음)([명세 §5.3](../../docs/sw/sw-header-design-spec.md#53-색상--선스타일--문자스타일--치수스타일-dropdown-2026-10-16), [사용 가이드 §7](../../docs/sw/sw-header-usage.md#색상--선문자치수스타일-dropdown-예-2026-10-16)). +## 글꼴·테마 - ```tsx - applyColor(option)} onColorModeChange={setColorMode} onColorInput={({ hex }) => applyHex(hex)} - lineStyle={lineStyle} lineTypes={lineTypes} lineWeights={lineWeights} - onLineTypeSelect={type => setLineStyle(s => ({ ...s, name: type.name }))} - textStyle={textStyle} textStyles={textStyles} onTextStyleSelect={style => setTextStyle(style)} - dimensionStyle={dimensionStyle} dimensionStyles={dimensionStyles} onDimensionStyleSelect={style => setDimensionStyle(style)} - /> - ``` -- 반응형 More: 좁은 헤더에서 더보기의 필드를 고르면 그 필드가 첫 칸(레이어 자리)에 표시되고 Dropdown이 바로 아래 열립니다. 레이어는 더보기에서 다시 고를 수 있으며, 전환은 UI 상태라 데이터 Callback을 호출하지 않습니다([명세 §5.4](../../docs/sw/sw-header-design-spec.md#54-반응형-more--대표-필드-전환-2026-10-16)). -- 실측 More(2026-10-19): Breakpoint 위에서 객체 수정 영역의 실제 남은 공간을 측정해 표시할 수 없는 메뉴만 More로 옮기고, 공간이 생기면 원래 자리·순서로 돌려놓습니다. 메뉴 열기·닫기는 Header 요소의 위치·폭을 바꾸지 않습니다([명세 §12.1](../../docs/sw/sw-header-design-spec.md#121-실측-more--실제-사용-가능한-공간-기준-2026-10-19)). Storybook의 홈 메뉴 예제는 `SW / Header` → `Home Menu`입니다. -- Text Stroke: Figma에 Stroke가 있는 텍스트만 검정 외곽선(14·16px 1.3px, 12px 1px)을 표시합니다. 자기 색 0.3px Stroke는 2026-10-16 추가 수정으로 제거했습니다. 더보기·Tooltip·`+ New`/`Open`은 제외([명세 §6.1](../../docs/sw/sw-header-design-spec.md#61-text-stroke-2026-10-16)). -- `SWHeaderInput`: 레이어 상세 등 상세 영역에서 쓰는 수정 가능 Input(Figma 26:11656, Default / Hover / 편집, caret `#E60403`). `value`(확정값) · `onValueChange`(임시값) · `onCommit`(Enter·Focus 이동, 유효 + 변경 시) · `onCancel`(Escape) · `valueType`(`text` / `number`) · `parse` · `readOnly` · `disabled`([명세 §5.5](../../docs/sw/sw-header-design-spec.md#55-레이어-상세-버튼--수정-가능한-input-2026-10-16)). -- Peer: `react`, `react-dom` `^19.0.0`. 런타임 dependency는 없습니다. -- 출력: `dist/index.js`(ESM, Figma SVG asset은 data URI로 포함, 임시 Figma URL 없음), `dist/*.d.ts`, `dist/styles.css`. -- CSS는 자동 import되지 않습니다. `@hm-design/sw/styles.css`를 한 번 import합니다. -- Registry에는 아직 게시하지 않았습니다. 설치·사용·Props는 [사용 가이드](../../docs/sw/sw-header-usage.md), 디자인 기준은 [디자인 명세](../../docs/sw/sw-header-design-spec.md)를 따릅니다. +- SW 기본 글꼴은 **Noto Sans KR**입니다(`--hm-sw-header-font-family: "Noto Sans KR", "Malgun Gothic", "Apple SD Gothic Neo", sans-serif`, 2026-10-20 확정, Figma의 Dotum은 의도적으로 대체). 패키지는 글꼴 파일을 포함하지 않으므로 앱이 Noto Sans KR 400 / 500 / 700을 로드합니다. +- Weight(400 / 700 적용 범위)는 사용자 확정값입니다. 상세는 [ai/AI_USAGE.md](./ai/AI_USAGE.md) §2, [ai/DESIGN_RULES.md](./ai/DESIGN_RULES.md) §3. +- `SWHeader` 밖에서 하위 컴포넌트를 쓰면 ``로 감쌉니다. `SWViewerHeader`·`SWViewerMenu`·`SWViewerPanel`·`SWFooter`·`SWFooterCommandLine`은 자기 루트에 SW 범위를 가집니다. +- 토큰(`--hm-sw-*`) 변경은 가장 바깥 SW 범위(``) 한 곳에서 합니다. Light/Dark 분기는 없습니다. 방법은 [ai/AI_USAGE.md](./ai/AI_USAGE.md) §3.1, 예제 [ExampleJ-Theme.tsx](./ai/examples/ExampleJ-Theme.tsx). + +## SW 모드 + +한 화면에는 하나의 모드만 씁니다(Header 하나). 모드 선택 기준은 [ai/AI_USAGE.md](./ai/AI_USAGE.md) §0입니다. + +| 모드 | 용도 | 컴포넌트 | +|---|---|---| +| SW 일반 모드 | 도면 **편집** SW 상단·하단(Figma 이지빔-SW `26:8944`, 49px Header) | `SWHeader`·개별 컨트롤, `SWPopup`, `SWToolButton`/`SWToolGroup`, 로고 클릭 메뉴, `SWFooter` | +| SW 뷰어 모드 | 도면 **보기** 화면 상단(참고 DWG/DXF 뷰어 실측, 52px Header) | `SWViewerHeader`, `SWViewerMenu`, `SWViewerPanel`과 패널 컨트롤 | + +## 공개 컴포넌트 (요약) + +| 영역 | 컴포넌트 | 안내 | +|---|---|---| +| 완성형 Header | `SWHeader`(문서·레이어·색상·선/문자/치수스타일 Dropdown, 속성Bar·속성창, 반응형 More, `controls`·`hiddenControls`·`menuOrder`·`documentOpenPlacement`·`leading`·`tools`) | 카탈로그 §1 | +| 개별 컨트롤 | `SWHeaderHome`, `SWHeaderDocumentTitle`, `SWHeaderLayerMenu`, `SWHeaderColorMenu`, `SWHeaderLineStyleMenu`, `SWHeaderTextStyleMenu`, `SWHeaderDimensionStyleMenu`, `SWHeaderInput`, `SWHeaderProperties`, `SWHeaderPropertyBar`, `SWHeaderPropertyPanel`, `SWHeaderActions`, `SWHeaderWindowControls` 등 | 카탈로그 §2 | +| Popup | `SWPopup`(속성창 프레임 + 자유 `children`) + `SWPopupSection` / `SWPopupRow`, 레이어·색상·선스타일 행 `SWPopupPropertyRow`, 게이지바 `SWSlider`(`appearance` `"panel"` / `"property"`), 선택 목록 `SWSelect`. SWHeader 필드 Dropdown은 Header 전용이라 Popup에 넣지 않습니다 | 카탈로그 §3 | +| 도구 막대 | `SWToolButton`(`text`·`pill`·`document`), `SWToolGroup`(`selection="single"` = Model/Layout 탭) | 카탈로그 §4 | +| 로고 클릭 메뉴 | `SWHeader`의 `homeMenu` + `SWHomeMenu` / `SWHomeMenuSection` / `SWHomeMenuItem` / `SWRecentFiles` / `useSWHomeMenuClose`(일반 모드 전용) | 카탈로그 §5 | +| 뷰어 모드 | `SWViewerHeader`, `SWViewerHeaderButton`, `SWViewerMenu`, `SWViewerIcon`, `SWViewerPanel`, `SWViewerSection`, `SWViewerField`, `SWViewerSwitch`, `SWViewerSlider`, `SWViewerInput`, `SWViewerButton`, `SWViewerBadge`, `SWViewerHint`, `SWViewerStatus` | 카탈로그 §9, [ai/VIEWER.md](./ai/VIEWER.md) | +| Footer | `SWFooter`, `SWFooterLayoutTabs`, `SWFooterCommandLine`과 부품 `SWFooterSideButton`·`SWFooterAuxGroup`·`SWFooterAuxButton`·`SWFooterToolButton`·`SWFooterAddSlot`·`SWFooterGuide`·`SWFooterMenu`(일반 모드 전용) | 카탈로그 §10, [ai/FOOTER.md](./ai/FOOTER.md) | +| 테마 | `SWTheme` | 위 "글꼴·테마" | + +로고·파일 처리·도면 렌더링·명령 실행은 각 프로그램이 Props와 Callback으로 담당합니다. 패키지에는 로고·메뉴 항목·명령이 없습니다. + +## AI 코딩 도구용 안내 + +다른 프로젝트의 AI 코딩 도구는 설치된 패키지의 `ai/` 폴더를 먼저 읽습니다: [AI_GUIDE.md](./ai/AI_GUIDE.md)(HMDesign 공통 진입점) → [AI_USAGE.md](./ai/AI_USAGE.md)(모드 선택·작업 순서·Import 규칙) → [COMPONENT_CATALOG.md](./ai/COMPONENT_CATALOG.md)(공개 API) → [DESIGN_RULES.md](./ai/DESIGN_RULES.md)(토큰·상태) → [COMPOSITION_PATTERNS.md](./ai/COMPOSITION_PATTERNS.md)(조합) → [VIEWER.md](./ai/VIEWER.md)·[FOOTER.md](./ai/FOOTER.md) → [examples/](./ai/examples)(공개 API만 쓰는 예제 A~J. B·F 파일명의 "Viewer"는 과거 이름이며 일반 모드 예제, 뷰어 모드는 H). + +## Storybook (HMDesign 저장소) + +SW Story는 40개입니다(`SW/Header` 20 · `SW/Footer` 6 · `SW/Popup` 3 · `SW/Viewer` 10 · `SW/Theme` 1). 이 중 11개는 `verification` 태그라 사이드바에서 기본으로 숨겨지며 직접 URL·태그 필터로 엽니다. + +- `SW/Header`: Overview, Interactive States, Logo Slot, Document Dropdown, Responsive More, Dropdown(개별 컨트롤 조합), Document Open, Hidden Sub Controls, Home Menu, Home Menu · 단독 사용 · 조합형 (+ verification 10) +- `SW/Footer`: 전체 Footer · 실제 조합, 도구 그룹별 표시, 도구 및 메뉴 변경 예제, 화면 폭 변화, 개별 부품 (+ verification 1) +- `SW/Popup`: Custom Content, Multiple Popups, Property Panel · 4개 비교(Story ID `sw-header--property-panel-compare`) +- `SW/Viewer`: Viewer Header, Menu Groups, Item States, Header + Dropdown, Settings Popup, Popup Content Variants, Variable Size Popups, Responsive Widths, SWHeader vs Viewer Header, Logo +- `SW/Theme`: Theme Inheritance + +## 빌드 (HMDesign 저장소) ```bash npm run build -w @hm-design/sw npm run typecheck -w @hm-design/sw ``` -## 추가 연결: 속성창·K 가이드 (2026-10-16) +`dist/styles.css`는 `src/theme/*.css`에서 만들어집니다. dist를 직접 편집하지 않습니다. -- `SWHeaderPropertyPanel` 및 property/group/selection 타입을 공개합니다. `SWHeader.propertyPanel`에 외부 데이터를 전달하면 기존 속성창 버튼·More와 연결됩니다. -- `propertyPanelOpen/onPropertyPanelOpenChange`로 Controlled 열림을 지원하며, 생략하면 내부 열림 상태를 사용합니다. 기존 `onPropertyPanelToggle`을 보존합니다. -- Text/Number/Select/Color/Slider/Computed, id 기반 동적 항목, 검증·확정·취소·외부 변경·ReadOnly/Disabled·그룹 펼침을 지원합니다. CAD 계산·선택·객체 변경은 호스트가 담당합니다. -- 상세 5개는 Figma 고정 크기와 Hover를 적용합니다. ByLayer/ByBlock은 정확히 하나가 표시되며, 기존 null 직접 색상 의미는 보존합니다. 레이어/선/문자/치수 목록은 Hover와 Selected 디자인이 같습니다. -- K는 기존 버튼을 재사용하고 원본 이미지 Pan/Zoom을 반복합니다. 640px 미만에서는 기존 More 항목에서도 같은 가이드를 표시합니다. Reduced Motion은 정적 이미지이며 기존 창 이동 1400ms는 유지합니다. -- 지정된 일반 text-stroke-width 선언·변수는 제거했고 검정 text-shadow와 상세 pill의 별도 Stroke는 보존했습니다(상세 pill Stroke도 아래 후속 5개 요구사항에서 제거됨). -- 사용 예시와 API는 [가이드 추가 절](../../docs/sw/sw-header-usage.md#속성창k-가이드-추가-연결-2026-10-16), 디자인 값은 [명세 추가 절](../../docs/sw/sw-header-design-spec.md#추가-수정-기준--속성창k-가이드-2026-10-16)을 확인하세요. -- 검증: 기존 17 + 신규 4 Story, [현재 실행 결과 및 NOT VERIFIED](../../docs/sw/sw-header-additional-verification-2026-10-16.md). 과거 로그는 보존합니다. +## 저장소 문서 -## 후속 5개 요구사항 API (2026-10-16) +아래 문서는 HMDesign 저장소에만 있고 npm 패키지에는 포함되지 않습니다(저장소 루트 기준 경로). -- `SWHeaderPropertyBar` / `SWHeaderPropertyBarProps`를 공개합니다. `propertyBar`로 selection/properties/onPropertyChange와 readOnly/disabled를 전달합니다. 속성창과 SWHeaderProperty/Selection 데이터를 공유하며, `propertyBarOpen/defaultPropertyBarOpen/onPropertyBarOpenChange`는 별도의 표시 상태입니다. 최대 폭 1222·높이 28px이고 Header 49px 아래에 표시됩니다. -- `SWHeaderControlId` / `SWHeaderControlConfig` / `SWHeader.controls`는 메뉴 자체의 전체 allowlist입니다. undefined는 기존 기본 구성, []는 선택적 컨트롤 없음입니다. id/visible/label과 배열 순서로 제거·복원·변경·재배치하며 More도 동일 구성을 따릅니다. 내부 옵션 배열·선택값 Props는 그대로입니다. -- Text Stroke Story의 지정 원본 이미지 블록·전용 import를 제거했습니다. 원본 PNG와 다른 비교 Story는 보존합니다. -- 상세 span의 `-webkit-text-stroke-width`와 미사용 `--hm-sw-header-solid-stroke-width`를 src/theme/sw.css에서 제거했습니다. build는 이 원본에서 dist/styles.css를 만드므로 dist만 편집하지 않습니다. 검정 text-shadow·SVG Stroke·상세 Hover는 보존합니다. -- 색상 추출 버튼은 로컬 Figma Default/Hover SVG를 사용합니다(24px/18px). 기존 `onColorPick`은 그대로이며 Hover는 Callback을 실행하지 않습니다. `26:11338` 돋보기 Overlay는 호스트 연동 대상입니다. -- Storybook은 기존 21개와 신규 Property Bar / Dynamic Controls / Colorize, 총 24개입니다. [최신 검증 기록](../../docs/sw/sw-header-followup-five-verification-2026-10-16.md)을 참조하세요. +- 사용 가이드 `docs/sw/sw-header-usage.md`, 디자인 명세 `docs/sw/sw-header-design-spec.md` +- 뷰어 모드 기준 `docs/sw/sw-viewer-mode-2026-10-19.md`, Footer Figma 매핑 `docs/sw/sw-footer-figma-mapping-2026-10-20.md` +- 날짜별 구현·검증 기록 `docs/sw/*-YYYY-MM-DD.md`(작성 당시 기록이며, 현재 기준은 이 README와 `ai/` 문서) +## 변경 요약 - -## 3차 API (2026-10-16) - -- `SWHeader.hiddenControls?: readonly SWHeaderHideableControlId[]` — `SWHeaderControlId` + `SWHeaderFrameControlId`(`home` / `windowMove` / `minimize` / `close`). 로고는 항상 표시하며 `home` 제거 시 정적 로고입니다. 제거한 요소는 공간·Popup·Callback이 없습니다. -- `SWHeader.menuOrder?: readonly SWHeaderMenuId[]` — 5개 유사 메뉴끼리만 순서 변경. 지정 id 우선, 누락 id는 기본 순서로 뒤에, 중복·알 수 없는 id 무시. More 목록도 같은 순서입니다. -- `SWHeaderPropertyPanelProps.shapeContent?: SWHeaderPropertyShapeContent` — `undefined` Figma 원형, `null`/`false` 빈 208×208 영역, ReactNode 또는 `(context: SWHeaderPropertyShapeContext) => ReactNode`. `SWHeader.propertyPanel`로도 전달됩니다. -- 하위 공개 컴포넌트에 선택적 표시 Props 추가(기본 true): `SWHeaderHome.interactive`, `SWHeaderProperties.showCaption/showBar/showPanel`, `SWHeaderActions.showPrint/showPopupGuide`, `SWHeaderWindowControls.showWindowMove/showMinimize/showClose`. -- Storybook: 기존 24개 + Composition, Property Panel 개별 4개, 4개 비교, 형상 Slot = 31개. - -## 속성 필드·게이지 (2026-10-19) - -- 속성창 공통 행은 Figma 26:12388 ~ 26:12649의 Default / Hover / On을 따릅니다. 숫자는 편집 On(`#0F0D0A`), 레이어·선스타일·색상은 Dropdown On(`#211D13`)이며 하이퍼링크·재료는 Default·Hover만 있습니다. -- 추가 API(모두 선택): `SWHeaderProperty.picker`(`"layer" | "lineStyle" | "color" | false`), `SWHeaderProperty.decimals`, `SWHeaderPropertyPanelProps.menus`(`SWHeaderPropertyMenus`). 필드 Dropdown은 Header Dropdown과 같은 목록 컴포넌트를 씁니다. [사용법](../../docs/sw/sw-header-usage.md#속성창k-가이드-추가-연결-2026-10-16), [검증 기록](../../docs/sw/sw-property-fields-verification-2026-10-19.md). -- 투명도 게이지는 빨강 채움 + 베이지 Track이며 Chrome·Firefox가 같은 그림을 씁니다([Firefox 게이지 기록](../../docs/sw/sw-header-firefox-range-close-verification-2026-10-19.md)). - -## AI 코딩 도구용 가이드 (2026-10-19) - -다른 프로젝트에서 AI 코딩 도구가 이 패키지를 재사용·조합·확장할 때는 설치된 패키지의 `ai/` 폴더를 먼저 읽습니다: [AI_GUIDE.md](./ai/AI_GUIDE.md)(HMDesign 공통 진입점: Web / SW / OrgChart / 혼합 선택, 패키지 분리, 결과 보고. 모든 HMDesign 패키지에 같은 사본, 2026-10-19 추가) → [AI_USAGE.md](./ai/AI_USAGE.md)(작업 순서·Import 규칙) → [COMPONENT_CATALOG.md](./ai/COMPONENT_CATALOG.md)(공개 API) → [DESIGN_RULES.md](./ai/DESIGN_RULES.md)(토큰·상태·Motion) → [COMPOSITION_PATTERNS.md](./ai/COMPOSITION_PATTERNS.md)(조합 방법) → [examples/](./ai/examples)(공개 API만 쓰는 예제 A~D). `ai/`는 npm 패키지(`files`)에 포함됩니다. 런타임 API는 바뀌지 않았습니다. - -## SW Footer (2026-10-20) - -하단 명령 막대 `SWFooter`(보조기능 버튼·3 × 2 보조기능 토글·바 안 명령창·명령 칸 68 × 47·분류 탭·명령어 전체보기), 도면 공간 탭 `SWFooterLayoutTabs`(+ · Layout · Model), 명령창 `SWFooterCommandLine`과 조합용 부품 `SWFooter*`를 추가했습니다(SW 일반 모드). 기준: Figma 이지빔-SW 26:10097과 부품 34개, 바 안 명령창·좁은 폭은 사용자 제공 실제 화면. 명령 실행·등록·Layout 생성은 호스트가 Callback으로 처리합니다. AI 사용 안내는 [ai/FOOTER.md](./ai/FOOTER.md), 노드 매핑은 [docs/sw/sw-footer-figma-mapping-2026-10-20.md](../../docs/sw/sw-footer-figma-mapping-2026-10-20.md), Storybook은 `SW/Footer`. +- **2026-10-20:** `SWSlider`, `SWSelect`, `SWPopupPropertyRow` 추가(Popup 레이어·색상·선스타일 = 속성창 picker). `SWFooter*` 추가. SW 기본 글꼴 Noto Sans KR 확정, 같은 날의 Dotum 기본값 철회. +- **2026-10-19:** 0.2.0 통합 개선 — `SWPopup` / `SWPopupSection` / `SWPopupRow`, `SWToolButton` / `SWToolGroup`, `SWHeader`의 `documentOpenPlacement`·`leading`·`tools`, 실측 More. 로고 클릭 메뉴(`SWHomeMenu` 계열), 뷰어 모드(`SWViewer*`). AI 안내(`ai/`) 포함. +- **2026-10-16:** 색상·선/문자/치수스타일 Dropdown, 속성Bar·속성창(`SWHeaderPropertyBar`·`SWHeaderPropertyPanel`), `controls`·`hiddenControls`·`menuOrder`, K 가이드, 창 이동 Hover Motion(1.4초). diff --git a/packages/sw/ai/AI_USAGE.md b/packages/sw/ai/AI_USAGE.md index e2ea9c6..9c2efc0 100644 --- a/packages/sw/ai/AI_USAGE.md +++ b/packages/sw/ai/AI_USAGE.md @@ -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` …)를 `` 안에 배치한다. 배치용 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 구성 값 — 디자인 확인 필요"로 보고한다(화면 인상을 크게 바꾸는 값은 구현 전에 사용자에게 확인). diff --git a/packages/sw/ai/COMPONENT_CATALOG.md b/packages/sw/ai/COMPONENT_CATALOG.md index fdfb618..b334020 100644 --- a/packages/sw/ai/COMPONENT_CATALOG.md +++ b/packages/sw/ai/COMPONENT_CATALOG.md @@ -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? }`) 또는 `