diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 6f1f425..0ecf933 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -46,6 +46,8 @@ const preview: Preview = { "OrgChart", ["Overview", "Department Colors", "Full Composition", "Expanded OrgChart"], "Center Graphic", + "SW", + ["Header", "Footer", "Popup", "Viewer", "Theme"], "*", ], }, diff --git a/docs/sw/storybook-simplification-qa/popup-property-panel-compare.png b/docs/sw/storybook-simplification-qa/popup-property-panel-compare.png new file mode 100644 index 0000000..b1e83a8 Binary files /dev/null and b/docs/sw/storybook-simplification-qa/popup-property-panel-compare.png differ diff --git a/docs/sw/storybook-simplification-qa/result.json b/docs/sw/storybook-simplification-qa/result.json new file mode 100644 index 0000000..e5e99b6 --- /dev/null +++ b/docs/sw/storybook-simplification-qa/result.json @@ -0,0 +1,71 @@ +[ + { + "n": "direct URL render: 42 SW Stories, no error display / page error", + "ok": true, + "d": [] + }, + { + "n": "removed Home Menu IDs absent from index", + "ok": true + }, + { + "n": "Popup › Property Panel: four states none/all/circle/expanded at 314 × 256/361/658/754", + "ok": true, + "d": [ + [ + "none", + 314, + 256 + ], + [ + "all", + 314, + 361 + ], + [ + "circle", + 314, + 658 + ], + [ + "expanded", + 314, + 754 + ] + ] + }, + { + "n": "sidebar SW order Header → Footer → Popup → Viewer → Theme", + "ok": true, + "d": [ + "Header", + "Footer", + "Popup", + "Viewer", + "Theme" + ] + }, + { + "n": "verification Stories not in sidebar", + "ok": true, + "d": [] + }, + { + "n": "Popup children order: Custom Content, Multiple Popups, Property Panel", + "ok": true, + "d": [ + "sw-popup--custom-content", + "sw-popup--multiple-popups", + "sw-header--property-panel-compare" + ] + }, + { + "n": "Property Panel listed once (under Popup only)", + "ok": true + }, + { + "n": "sidebar link opens moved Story with same ID", + "ok": true, + "d": "http://127.0.0.1:4479/?path=/story/sw-header--property-panel-compare" + } +] \ No newline at end of file diff --git a/docs/sw/storybook-simplification-qa/sidebar.json b/docs/sw/storybook-simplification-qa/sidebar.json new file mode 100644 index 0000000..4c4e246 --- /dev/null +++ b/docs/sw/storybook-simplification-qa/sidebar.json @@ -0,0 +1,182 @@ +[ + [ + "sw-header", + "component", + "Header" + ], + [ + "sw-header--composed-controls", + "story", + "Dropdown" + ], + [ + "sw-header--home-menu", + "story", + "Home Menu" + ], + [ + "sw-header--home-menu-standalone", + "story", + "Home Menu · 단독 사용 · 조합형" + ], + [ + "sw-header--document-open", + "story", + "Document Open" + ], + [ + "sw-header--hidden-sub-controls", + "story", + "Hidden Sub Controls" + ], + [ + "sw-header--overview", + "story", + "Overview" + ], + [ + "sw-header--interactive-states", + "story", + "Interactive States" + ], + [ + "sw-header--logo-slot", + "story", + "Logo Slot" + ], + [ + "sw-header--document-dropdown", + "story", + "Document Dropdown" + ], + [ + "sw-header--responsive-more", + "story", + "Responsive More" + ], + [ + "sw-footer", + "component", + "Footer" + ], + [ + "sw-footer--default", + "story", + "기본 Footer" + ], + [ + "sw-footer--full-footer", + "story", + "전체 Footer · 실제 조합" + ], + [ + "sw-footer--tool-groups", + "story", + "도구 그룹별 표시" + ], + [ + "sw-footer--states", + "story", + "Hover / Active / Selected / Disabled" + ], + [ + "sw-footer--custom-content", + "story", + "도구 및 메뉴 변경 예제" + ], + [ + "sw-footer--responsive", + "story", + "화면 폭 변화" + ], + [ + "sw-footer--parts", + "story", + "개별 부품 (조합용)" + ], + [ + "sw-popup", + "component", + "Popup" + ], + [ + "sw-popup--custom-content", + "story", + "Custom Content" + ], + [ + "sw-popup--multiple-popups", + "story", + "Multiple Popups" + ], + [ + "sw-header--property-panel-compare", + "story", + "Property Panel · 4개 비교" + ], + [ + "sw-viewer", + "component", + "Viewer" + ], + [ + "sw-viewer--viewer-header", + "story", + "Viewer Header" + ], + [ + "sw-viewer--menu-groups", + "story", + "Menu Groups" + ], + [ + "sw-viewer--states", + "story", + "Item States" + ], + [ + "sw-viewer--dropdowns", + "story", + "Header + Dropdown" + ], + [ + "sw-viewer--settings-panel", + "story", + "Settings Popup" + ], + [ + "sw-viewer--content-variants", + "story", + "Popup Content Variants" + ], + [ + "sw-viewer--variable-size", + "story", + "Variable Size Popups" + ], + [ + "sw-viewer--responsive", + "story", + "Responsive Widths" + ], + [ + "sw-viewer--compare-with-sw-header", + "story", + "SWHeader vs Viewer Header" + ], + [ + "sw-viewer--logo", + "story", + "Logo" + ], + [ + "sw-theme", + "component", + "Theme" + ], + [ + "sw-theme--theme-inheritance", + "story", + "Theme Inheritance" + ] +] \ No newline at end of file diff --git a/docs/sw/storybook-simplification-qa/sidebar.png b/docs/sw/storybook-simplification-qa/sidebar.png new file mode 100644 index 0000000..253aa50 Binary files /dev/null and b/docs/sw/storybook-simplification-qa/sidebar.png differ diff --git a/docs/sw/sw-header-usage.md b/docs/sw/sw-header-usage.md index 4283dae..c0f05b4 100644 --- a/docs/sw/sw-header-usage.md +++ b/docs/sw/sw-header-usage.md @@ -455,7 +455,9 @@ Tooltip은 45 × 17px, 검정 80% 배경과 흰색 12px/400 글자입니다. Too npm run storybook ``` -현재(2026-10-19, 홈 메뉴 통합 후) `SW / Header`에는 27개 Story가 있습니다(사이드바 기본 표시 12개 + `verification` 태그 15개). 이전 시점의 Story 표는 [1차 정리 보고 §2](./sw-first-pass-cleanup-review-2026-10-19.md#2-storybook-전체-목록-및-분류), 홈 메뉴 통합 후 목록은 [홈 메뉴 통합·실측 More 보고](./sw-header-home-menu-responsive-2026-10-19.md)를 봅니다. 아래 문단은 Story를 추가한 시점별 설명입니다. +> **현재 기준(2026-10-20 SW Storybook 간소화):** SW 메뉴 순서는 `Header → Footer → Popup → Viewer → Theme`입니다. `SW / Header`에는 20개 Story가 있습니다(사이드바 기본 표시 10개 + `verification` 태그 10개). `Property Panel · 4개 비교`는 사이드바에서 `SW / Popup` 아래로 옮겼고 ID(`sw-header--property-panel-compare`)는 그대로입니다. `Window Move Motion`·`K Guide`는 `verification` 태그로 숨겼고, `Home Menu · 단독 사용 · 조합형`은 개별 부품 예제로 사이드바에 표시합니다. 테스트·문서에서 쓰지 않던 Home Menu Figma 비교 Story 6개(`sw-header--home-menu-figma`, `-capture-active`, `-capture-outline`, `-capture-recent`, `-variants`, `-recent-files`)와 `Home Menu`의 Figma 스크린샷 비교 섹션은 제거했습니다. Figma 원본은 `docs/sw/figma-additional/screenshots/`에 있습니다. 상세: [SW Storybook 간소화 보고](./sw-storybook-simplification-2026-10-20.md). 아래는 작성 당시 기록입니다. + +(2026-10-19 기록) 홈 메뉴 통합 후 `SW / Header`에는 27개 Story가 있습니다(사이드바 기본 표시 12개 + `verification` 태그 15개). 이전 시점의 Story 표는 [1차 정리 보고 §2](./sw-first-pass-cleanup-review-2026-10-19.md#2-storybook-전체-목록-및-분류), 홈 메뉴 통합 후 목록은 [홈 메뉴 통합·실측 More 보고](./sw-header-home-menu-responsive-2026-10-19.md)를 봅니다. 아래 문단은 Story를 추가한 시점별 설명입니다. 2026-10-19 홈 메뉴 통합: 기존 `SW / Home Menu` 메뉴는 사이드바에서 제거하고 `SW / Header`로 옮겼습니다. 사이드바에는 `Home Menu`(`sw-header--home-menu`: 로고 클릭 열기/닫기·이벤트 기록, 헤더 폭 조절, Figma 26:10591 비교, Default/Hover/Active, 최근파일 하위 패널, 속성창·SWPopup·Escape 통합) 하나만 표시합니다. Figma 비교 캔버스·Variant·데이터 변경·단독 사용·속성Bar 비교 등은 `sw-header--home-menu-*` ID의 `verification` 태그 Story로 남아 직접 URL과 사이드바 태그 필터로 엽니다. `Overview`의 로고도 같은 홈 메뉴를 엽니다. `Responsive More` 첫 섹션 "실제 사용 가능한 공간 기준"은 헤더 폭 Range와 로고 오른쪽 버튼·추가 도구·홈 메뉴 On/Off로 실측 More의 이동·복귀를 확인합니다. 홈 메뉴는 SW 일반 모드 전용이며 `SW / Viewer`에는 없습니다. diff --git a/docs/sw/sw-storybook-simplification-2026-10-20.md b/docs/sw/sw-storybook-simplification-2026-10-20.md new file mode 100644 index 0000000..6d62203 --- /dev/null +++ b/docs/sw/sw-storybook-simplification-2026-10-20.md @@ -0,0 +1,70 @@ +# SW Storybook 메뉴·콘텐츠 간소화 (2026-10-20) + +범위: SW Storybook(`src/sw/*.stories.tsx`, `.storybook/preview.tsx` storySort) 정리만 합니다. SW 컴포넌트 소스, 공개 Props/Events, Token, Web(UI)·OrgChart는 변경하지 않았습니다. 기준 HEAD `47972c5`(`feature/sw-package`). Home Menu는 2026-10-19 결정대로 `SW / Header` 아래에 유지합니다. + +## 1. 메뉴 구조 + +| | 변경 전 | 변경 후 | +|---|---|---| +| SW 순서 | Footer → Header → Popup → Theme → Viewer (알파벳) | **Header → Footer → Popup → Viewer → Theme** (`storySort`) | +| SW/Header | 표시 12 + verification 15 | 표시 10 + verification 10 | +| SW/Footer | 표시 8 | 표시 7 + verification 1 | +| SW/Popup | 표시 2 | 표시 3 (`Property Panel · 4개 비교` 이동) | +| SW/Viewer / SW/Theme | 10 / 1 | 변경 없음 | + +변경 후 사이드바 (`storybook-simplification-qa/sidebar.json`): + +- **Header:** Dropdown · Home Menu · Home Menu · 단독 사용 · 조합형 · Document Open · Hidden Sub Controls · Overview · Interactive States · Logo Slot · Document Dropdown · Responsive More +- **Footer:** 기본 Footer · 전체 Footer · 실제 조합 · 도구 그룹별 표시 · Hover / Active / Selected / Disabled · 도구 및 메뉴 변경 예제 · 화면 폭 변화 · 개별 부품 (조합용) +- **Popup:** Custom Content · Multiple Popups · Property Panel · 4개 비교 +- **Viewer:** Viewer Header · Menu Groups · Item States · Header + Dropdown · Settings Popup · Popup Content Variants · Variable Size Popups · Responsive Widths · SWHeader vs Viewer Header · Logo +- **Theme:** Theme Inheritance + +## 2. 변경 내용 + +| 구분 | Story (ID) | 처리 | 근거 | +|---|---|---|---| +| 이동 | `sw-header--property-panel-compare` | 사이드바만 `SW/Popup`으로 이동. 새 파일 `sw-property-panel.stories.tsx`(meta `id: "sw-header"`), 렌더 코드는 `sw-header.stories.tsx`의 `PropertyPanelComparePage`(excludeStories) 그대로 | 사용자 요청. ID·이름·4상태 화면 유지 | +| 숨김 | `sw-header--window-move-motion` | `verification` 태그 | GIF 프레임 검증. 테스트 5개가 URL로 사용 | +| 숨김 | `sw-header--k-guide` | `verification` 태그 | Overview와 같은 Header 화면. 테스트 3개가 URL로 사용 | +| 숨김 | `sw-footer--figma-variants` | `verification` 태그 (삭제 안 함) | Figma 35노드 비교. [Footer Figma 매핑 문서](./sw-footer-figma-mapping-2026-10-20.md)가 참조하며 이를 대신할 자동 검증이 없음 | +| 표시 | `sw-header--home-menu-standalone` | `verification` 태그 제거 | Header 없이 쓰는 개별 부품(SWHomeMenuSection / SWHomeMenuItem) 예제 | +| 삭제 | `sw-header--home-menu-figma` | Story 삭제 | Figma 1:1 스크린샷 비교. 테스트·문서 참조 없음 | +| 삭제 | `sw-header--home-menu-capture-active` / `-capture-outline` / `-capture-recent` | Story 삭제 | 비교 캔버스. 참조 없음 (`-capture-default`는 테스트가 사용하므로 유지) | +| 삭제 | `sw-header--home-menu-variants` | Story 삭제 | `Home Menu`의 Default / Variant2 / Variant3 섹션과 중복 | +| 삭제 | `sw-header--home-menu-recent-files` | Story 삭제 | `Home Menu`의 최근파일 섹션과 중복 + Figma 스크린샷 | +| 섹션 정리 | `sw-header--home-menu` | "Figma 26:10591 비교" 섹션의 Figma 이미지를 빼고 "열림 (현재 폭)"으로 변경. 최근파일 섹션의 Figma 이미지 2개 제거 | 사용법 중심. 구현 화면은 그대로 | + +삭제한 파일 (`src/sw/assets/home-menu/`): `figma-26-10591.png`, `figma-662-67267.png`, `662-67331_recent-files.png`, `662-67471_file-preview-2depth.png`. 네 파일 모두 `docs/sw/figma-additional/screenshots/`의 원본(`26-10591_home-on.png`, `662-67267_home-on-popup-guide.png`, `662-67331_recent-files.png`, `662-67471_file-preview-2depth.png`)과 md5가 같은 복사본이며, 원본은 보존합니다. 사용하지 않게 된 Story CSS 2개(`sw-home-menu-story__figma-row`, `__figma-fit`)도 제거했습니다. + +## 3. 유지한 검증용 Story (verification, URL로 접근 가능) + +`sw-header--home-menu-capture-default` · `-header-composition` · `-integration` · `-capture-responsive` (home-menu-integration 테스트) · `-dynamic-data` (Props 데이터 변경 예제) · `-property-bar-check` · `-capture-property-bar` (속성Bar 차이 3건 **승인 대기**, [Home Menu 통합 보고](./sw-home-menu-integration-2026-10-19.md)) · `sw-header--detail-buttons` · `sw-header--window-move-motion` · `sw-header--k-guide` · `sw-footer--figma-variants`. + +## 4. Story ID + +- 367 → 361개. 삭제한 6개를 뺀 나머지 ID는 모두 유지되었습니다. 바뀐 항목은 tags 4개, title 1개(`property-panel-compare`: SW/Header → SW/Popup)뿐입니다. +- SW 외 index 항목 319개(Web·OrgChart·Center Graphic·Theme 등)는 값과 순서가 바뀌지 않았습니다. +- 삭제한 ID는 `packages/sw/tests/storybook-inventory.mjs`의 `retiredHomeMenuCompareIds`, 이동한 ID는 `movedToPopupIds`에 기록했습니다. + +## 5. 검증 (2026-10-20 실제 실행) + +| 항목 | 결과 | +|---|---| +| `npm run build-storybook` | PASS | +| `npm run typecheck` | PASS | +| `npm run check:ai-docs` | PASS | +| `packages/sw/tests/storybook-simplification.browser.mjs` (신규) | **8/8 PASS**: SW Story 42개 직접 URL 렌더·오류 0, 삭제 ID 없음, Popup의 4상태 314 × 256/361/658/754, 사이드바 순서, 숨김 Story 미표시, Popup 순서, 중복 표시 없음, 이동 Story 링크 ID 유지 | +| `home-menu-integration.browser.mjs` | 22/23. FAIL 1건(`without homeMenu: logo click…`)은 기준선 `47972c5`에서도 같은 결과로 실패하는 **기존 실패** | +| `storybook-unused-removal.browser.mjs` | render 순회에 `movedToPopupIds`를 추가해서 Popup으로 옮긴 `property-panel-compare`도 검사합니다(신규 검사 1건 PASS). 검사 수 98 → 93: 의도적으로 삭제한 6개 render만 빠졌고, 나머지 검사 이름과 PASS/FAIL 상태는 기준선과 같습니다. FAIL 5건은 모두 기준선 `47972c5`에서도 실패하는 **기존 실패**(10-19 시점 inventory·source 스냅샷 비교)입니다. 그중 `byte-identical` 항목의 목록에는 이번에 의도적으로 수정한 export(`WindowMoveMotion`, `KGuide`, `PropertyPanelCompare`)가 추가로 들어 있습니다 | +| `dropdown-consolidation.browser.mjs` | 기준선에서도 같은 inventory 스냅샷 FAIL 5건 (기존 실패). 변경 후에는 실행하지 않음 | +| `followup-four`, `property-fields` | 실행 불가 (기존): 첫 단계에서 10-19에 retired된 `property-bar` / `property-fields` Story를 엶 | +| SW Viewer·Footer·Theme 기능 회귀 | 재실행하지 않음. 컴포넌트·Story 렌더 코드가 바뀌지 않았고, 이번 직접 URL 렌더 검사로 대신함 | + +증거: [storybook-simplification-qa/](./storybook-simplification-qa/) (`result.json`, `sidebar.json`, `sidebar.png`, `popup-property-panel-compare.png`). + +## 6. 남은 개선 항목 + +- Footer Story 이름만 한국어(`기본 Footer` 등)이고 다른 SW 메뉴는 영어입니다. 이름은 바뀌어도 ID가 유지되지만, Footer Figma 매핑 문서가 이름으로 참조하고 있어 이번에는 바꾸지 않았습니다. +- SW Story는 모두 `controls: { disable: true }`라서 Controls와 Props를 대조할 Playground Story가 없습니다. +- 과거 시점 스냅샷과 비교하는 테스트(`storybook-unused-removal`, `dropdown-consolidation`, `overview`, `detail-buttons`)와, retired Story를 여는 테스트(`followup-four`, `property-fields`)는 현재 상태 기준으로 다시 정리할 필요가 있습니다. diff --git a/packages/sw/tests/storybook-inventory.mjs b/packages/sw/tests/storybook-inventory.mjs index 2493ad3..fc2b5c6 100644 --- a/packages/sw/tests/storybook-inventory.mjs +++ b/packages/sw/tests/storybook-inventory.mjs @@ -21,6 +21,11 @@ export const retiredToolIds = ["sw-tool--tool-buttons"] // SW/Header as sw-header--home-menu (sidebar) and sw-header--home-menu-* (verification tag, reachable by URL). export const movedHomeMenuIds = Object.fromEntries(["figma-home-on:figma", "capture-default", "capture-active", "capture-outline", "capture-recent", "header-composition", "variants", "dynamic-data", "standalone", "recent-files-panel:recent-files", "property-bar-check", "capture-property-bar", "integration", "capture-responsive"] .map(entry => entry.split(":")).map(([from, to = from]) => [`sw-home-menu--${from}`, `sw-header--home-menu-${to}`])) +// 2026-10-20 (SW Storybook simplification, user request): Figma screenshot comparisons and duplicate Variant pages that +// no test or document used were removed; the Figma originals stay in docs/sw/figma-additional/screenshots/. +export const retiredHomeMenuCompareIds = ["figma", "capture-active", "capture-outline", "capture-recent", "variants", "recent-files"].map(id => `sw-header--home-menu-${id}`) +// 2026-10-20: Property Panel · 4개 비교 moved to SW/Popup in the sidebar; its ID is unchanged (meta id "sw-header"). +export const movedToPopupIds = ["sw-header--property-panel-compare"] export const integratedChangedFiles = [ 'packages/sw/README.md', 'packages/sw/package.json', 'packages/sw/build.mjs', 'packages/sw/ai/AI_USAGE.md', 'packages/sw/ai/COMPONENT_CATALOG.md', 'packages/sw/ai/COMPOSITION_PATTERNS.md', 'packages/sw/ai/DESIGN_RULES.md', diff --git a/packages/sw/tests/storybook-simplification.browser.mjs b/packages/sw/tests/storybook-simplification.browser.mjs new file mode 100644 index 0000000..faf57c1 --- /dev/null +++ b/packages/sw/tests/storybook-simplification.browser.mjs @@ -0,0 +1,64 @@ +// 2026-10-20 SW Storybook simplification: sidebar order, hidden verification Stories, removed IDs, direct URL render of +// every SW Story and the moved Property Panel (SW/Popup, ID sw-header--property-panel-compare). +// Usage: build Storybook first, then node packages/sw/tests/storybook-simplification.browser.mjs [evidence-dir] +import { createRequire } from 'node:module' +import { readFile, writeFile, mkdir } from 'node:fs/promises' +import path from 'node:path' +import http from 'node:http' +const runtime = process.env.SW_RUNTIME_MODULES ?? 'C:/Users/user/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules' +const require = createRequire(path.join(runtime, 'index.js')) +const { chromium } = require('playwright') +const out = path.resolve(process.argv[2] ?? 'docs/sw/storybook-simplification-qa'); await mkdir(out, { recursive: true }) +const root = path.resolve('storybook-static'), mime = { '.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css', '.json': 'application/json', '.svg': 'image/svg+xml', '.png': 'image/png', '.ttf': 'font/ttf', '.woff2': 'font/woff2' } +const server = http.createServer(async (req, res) => { try { const p = new URL(req.url, 'http://localhost').pathname, file = path.resolve(root, '.' + decodeURIComponent(p === '/' ? '/index.html' : p)); res.setHeader('Content-Type', mime[path.extname(file)] ?? 'application/octet-stream'); res.end(await readFile(file)) } catch { res.writeHead(404).end() } }) +await new Promise(r => server.listen(0, '127.0.0.1', r)); const base = `http://127.0.0.1:${server.address().port}` +const browser = await chromium.launch({ headless: true, executablePath: process.env.SW_CHROME_PATH ?? 'C:/Program Files/Google/Chrome/Application/chrome.exe' }) +const checks = []; const check = (n, ok, d) => { checks.push({ n, ok, d }); console.log(ok ? 'PASS' : 'FAIL', n, ok ? '' : JSON.stringify(d)) } +const index = JSON.parse(await readFile(path.join(root, 'index.json'), 'utf8')) +const sw = Object.values(index.entries).filter(e => e.type === 'story' && e.title.startsWith('SW/')) +// 1. every SW story renders by direct URL without page errors +const page = await browser.newPage({ viewport: { width: 1920, height: 1000 } }) +let errors = []; page.on('pageerror', e => errors.push(e.message)); page.on('console', m => { if (m.type() === 'error') errors.push(m.text()) }) +const bad = [] +for (const e of sw) { + errors = [] + await page.goto(`${base}/iframe.html?id=${e.id}&viewMode=story`) + try { await page.locator('#storybook-root > *').first().waitFor({ timeout: 15000 }) } catch { bad.push([e.id, 'no root']) ; continue } + await page.waitForTimeout(150) + const err = await page.locator('.sb-show-errordisplay').count() + if (err || errors.length) bad.push([e.id, errors.slice(0, 2)]) +} +check(`direct URL render: ${sw.length} SW Stories, no error display / page error`, bad.length === 0, bad) +// 2. removed IDs are gone +const removed = ['figma', 'capture-active', 'capture-outline', 'capture-recent', 'variants', 'recent-files'].map(id => `sw-header--home-menu-${id}`) +check('removed Home Menu IDs absent from index', removed.every(id => !index.entries[id])) +// 3. Property panel in Popup: four states +await page.goto(`${base}/iframe.html?id=sw-header--property-panel-compare&viewMode=story`) +await page.locator('[data-compare]').first().waitFor() +await page.waitForTimeout(300) +const cells = await page.locator('[data-compare]').evaluateAll(list => list.map(c => { const r = c.querySelector('.hm-sw-property').getBoundingClientRect(); return [c.dataset.compare, Math.round(r.width), Math.round(r.height)] })) +check('Popup › Property Panel: four states none/all/circle/expanded at 314 × 256/361/658/754', JSON.stringify(cells) === JSON.stringify([['none', 314, 256], ['all', 314, 361], ['circle', 314, 658], ['expanded', 314, 754]]), cells) +await page.screenshot({ path: path.join(out, 'popup-property-panel-compare.png'), fullPage: true }) +// 4. manager sidebar +const m = await browser.newPage({ viewport: { width: 1600, height: 2400 } }) +await m.goto(`${base}/?path=/story/sw-header--overview`) +await m.locator('[data-item-id="sw-header--overview"]').waitFor() +for (const c of ['sw-footer', 'sw-popup', 'sw-viewer', 'sw-theme']) { const b = m.locator(`[data-item-id="${c}"] > button[aria-expanded="false"]`); if (await b.count()) await b.click() } +await m.waitForTimeout(500) +const rows = await m.locator('#storybook-explorer-tree [data-item-id^="sw-"]').evaluateAll(list => list.map(e => [e.dataset.itemId, e.dataset.nodetype, e.textContent.replace('Skip to content', '').trim()])) +await writeFile(path.join(out, 'sidebar.json'), JSON.stringify(rows, null, 1)) +const comps = rows.filter(r => r[1] === 'component').map(r => r[2]) +check('sidebar SW order Header → Footer → Popup → Viewer → Theme', JSON.stringify(comps) === JSON.stringify(['Header', 'Footer', 'Popup', 'Viewer', 'Theme']), comps) +const hidden = ['sw-header--window-move-motion', 'sw-header--k-guide', 'sw-footer--figma-variants', 'sw-header--detail-buttons', 'sw-header--home-menu-capture-default'] +check('verification Stories not in sidebar', rows.every(r => !hidden.includes(r[0])), rows.filter(r => hidden.includes(r[0]))) +const popupRows = await m.locator('#storybook-explorer-tree [data-item-id]').evaluateAll(list => list.map(e => e.dataset.itemId)) +const pi = popupRows.indexOf('sw-popup') +check('Popup children order: Custom Content, Multiple Popups, Property Panel', JSON.stringify(popupRows.slice(pi + 1, pi + 4)) === JSON.stringify(['sw-popup--custom-content', 'sw-popup--multiple-popups', 'sw-header--property-panel-compare']), popupRows.slice(pi + 1, pi + 4)) +const headerIds = rows.filter(r => r[0].startsWith('sw-header--')).map(r => r[0]) +check('Property Panel listed once (under Popup only)', headerIds.filter(id => id === 'sw-header--property-panel-compare').length === 1) +await m.locator('[data-item-id="sw-header--property-panel-compare"]').click(); await m.waitForTimeout(800) +check('sidebar link opens moved Story with same ID', m.url().includes('sw-header--property-panel-compare'), m.url()) +await m.screenshot({ path: path.join(out, 'sidebar.png'), clip: { x: 0, y: 0, width: 320, height: 2400 } }) +await writeFile(path.join(out, 'result.json'), JSON.stringify(checks, null, 1)) +console.log(checks.filter(c => c.ok).length + '/' + checks.length + ' PASS') +await browser.close(); server.close() diff --git a/packages/sw/tests/storybook-unused-removal.browser.mjs b/packages/sw/tests/storybook-unused-removal.browser.mjs index 97309db..f348a30 100644 --- a/packages/sw/tests/storybook-unused-removal.browser.mjs +++ b/packages/sw/tests/storybook-unused-removal.browser.mjs @@ -8,7 +8,7 @@ import { execFileSync } from 'node:child_process' import path from 'node:path' import http from 'node:http' import { parse } from '@babel/parser' -import { swStoryEntries, retiredUnusedDemoIds, integratedStoryIds, integratedChangedFiles } from './storybook-inventory.mjs' +import { swStoryEntries, retiredUnusedDemoIds, integratedStoryIds, integratedChangedFiles, movedToPopupIds } from './storybook-inventory.mjs' const out = path.resolve(process.argv[2] ?? 'docs/sw/storybook-unused-story-removal-qa/verify') const qa = 'docs/sw/storybook-unused-story-removal-qa/before' @@ -92,7 +92,10 @@ try { check('removed URL renders no SW Story', await page.locator('.hm-sw-header, .hm-sw-theme').count() === 0) report.errors.length = 0 // the missing-story error above is expected; start the regression clean - for (const entry of afterSW) { + // 2026-10-20: Property Panel · 4개 비교 moved to SW/Popup (same sw-header-- ID), so it is added to the render pass. + const moved = movedToPopupIds.map(id => afterIndex.entries[id]).filter(Boolean) + check('inventory: moved Popup Story keeps its sw-header-- ID under SW/Popup', moved.length === movedToPopupIds.length && moved.every(e => e.title === 'SW/Popup'), moved.map(e => [e.id, e.title])) + for (const entry of [...afterSW, ...moved]) { await goto(entry.id.replace('sw-header--', '')) check(`render ${entry.id}`, !(await page.locator('.sb-errordisplay').isVisible())) } diff --git a/src/sw/assets/home-menu/662-67331_recent-files.png b/src/sw/assets/home-menu/662-67331_recent-files.png deleted file mode 100644 index ab32fa6..0000000 Binary files a/src/sw/assets/home-menu/662-67331_recent-files.png and /dev/null differ diff --git a/src/sw/assets/home-menu/662-67471_file-preview-2depth.png b/src/sw/assets/home-menu/662-67471_file-preview-2depth.png deleted file mode 100644 index 8e9f208..0000000 Binary files a/src/sw/assets/home-menu/662-67471_file-preview-2depth.png and /dev/null differ diff --git a/src/sw/assets/home-menu/figma-26-10591.png b/src/sw/assets/home-menu/figma-26-10591.png deleted file mode 100644 index 2aee93c..0000000 Binary files a/src/sw/assets/home-menu/figma-26-10591.png and /dev/null differ diff --git a/src/sw/assets/home-menu/figma-662-67267.png b/src/sw/assets/home-menu/figma-662-67267.png deleted file mode 100644 index efebf12..0000000 Binary files a/src/sw/assets/home-menu/figma-662-67267.png and /dev/null differ diff --git a/src/sw/sw-footer.stories.tsx b/src/sw/sw-footer.stories.tsx index 89a2709..32954db 100644 --- a/src/sw/sw-footer.stories.tsx +++ b/src/sw/sw-footer.stories.tsx @@ -221,6 +221,8 @@ const SMALL_COMMAND = { width: 120, ["--hm-sw-footer-command-expanded-height" as export const FigmaVariants: Story = { name: "Figma 디자인별 Variant (35 노드)", + // 2026-10-20 sidebar simplification: Figma node verification; ID and direct URL kept. + tags: ["verification"], render: () => ( 요청된 35개 노드 전체. 왼쪽 = Figma 렌더(get_screenshot), 오른쪽 = 같은 순서의 구현 상태(Hover는 Story 전용 data-sb-hover로 고정). 노드 → 컴포넌트·Props 매핑은 docs/sw/sw-footer-figma-mapping-2026-10-20.md.} /> diff --git a/src/sw/sw-header-home-menu.stories.tsx b/src/sw/sw-header-home-menu.stories.tsx index 8997efd..d137436 100644 --- a/src/sw/sw-header-home-menu.stories.tsx +++ b/src/sw/sw-header-home-menu.stories.tsx @@ -13,15 +13,13 @@ import { figmaHomeMenuItemIds, figmaHomeMenuSections, figmaRecentFiles, figmaTileNodes, figmaTitleNodes, withRecentFiles, } from "./sw-home-menu-fixture" import placeholderLogo from "./assets/sw-header-logo-placeholder.svg" -import figmaHomeOn from "./assets/home-menu/figma-26-10591.png" -import figmaHomeOnOutline from "./assets/home-menu/figma-662-67267.png" -import figmaRecent from "./assets/home-menu/662-67331_recent-files.png" -import figmaPreview from "./assets/home-menu/662-67471_file-preview-2depth.png" import figmaPropertyBar from "./assets/home-menu/figma-26-10492.png" // Owner: docs/sw/figma-additional/analysis-report.md (Figma rj6wpsfk24lOWvWiVRAANP 26:10591 / 662:67267). // 2026-10-19: the former SW/Home Menu Stories live under SW/Header (SW normal mode only; SW/Viewer has no logo menu). -// "Home Menu" is the sidebar Story; the other Stories keep their checks reachable by URL (verification tag). +// "Home Menu" and "Home Menu · 단독 사용 · 조합형" are the sidebar Stories; the other Stories keep their checks reachable +// by URL (verification tag). 2026-10-20: Figma screenshot comparisons that no test or document used were removed; +// the Figma originals stay in docs/sw/figma-additional/screenshots/. const KICKER = "HM DESIGN SYSTEM / SW" const meta = { @@ -136,21 +134,16 @@ export const HomeMenu: Story = { - + - Figma 26:10591 home on {tileTable} - +
{log => log}
-
- Figma 662:67331 최근파일 - Figma 662:67471 파일출력 2뎁스 -
@@ -159,38 +152,16 @@ export const HomeMenu: Story = { ), } -export const HomeMenuFigma: Story = { - name: "Home Menu · Figma 재현 (26:10591)", - tags: ["verification"], - render: () => ( - - - -
-
- -
Figma 26:10591 home on
-
-
- ), -} - -/** 1:1 capture canvas for pixel comparison with the Figma 1920 x 77 frame (no story page chrome). */ -function FigmaCanvas({ active, accent, recent }: { active?: boolean; accent?: SWHomeMenuAccent; recent?: boolean }) { - const sections = recent ? withRecentFiles(figmaHomeMenuSections, ) : figmaHomeMenuSections +/** 1:1 capture canvas at the Figma 1920 x 77 frame (no story page chrome); home-menu-integration.browser.mjs measures it. */ +function FigmaCanvas() { return ( -
+
{/* The integrated placement (measured by SWHeader), not a fixed x: it must land on Figma x 375. */} - +
) } export const HomeMenuCaptureDefault: Story = { name: "Home Menu · 비교 캔버스 · Default", tags: ["!autodocs", "verification"], render: () => } -export const HomeMenuCaptureActive: Story = { name: "Home Menu · 비교 캔버스 · Variant3", tags: ["!autodocs", "verification"], render: () => } -export const HomeMenuCaptureOutline: Story = { name: "Home Menu · 비교 캔버스 · outline", tags: ["!autodocs", "verification"], render: () => } -export const HomeMenuCaptureRecent: Story = { name: "Home Menu · 비교 캔버스 · 최근파일", tags: ["!autodocs", "verification"], render: () => } export const HomeMenuHeaderComposition: Story = { name: "Home Menu · Header 조합 · 로고 클릭", @@ -206,27 +177,6 @@ export const HomeMenuHeaderComposition: Story = { ), } -export const HomeMenuVariants: Story = { - name: "Home Menu · 3가지 Variant", - tags: ["verification"], - render: () => ( - - - - - - - - - - - - {tileTable} - - ), -} - function DynamicDemo() { const [sections, setSections] = useState(figmaHomeMenuSections) const [selection, setSelection] = useState<"multiple" | "single">("multiple") @@ -304,7 +254,6 @@ function StandaloneDemo() { export const HomeMenuStandalone: Story = { name: "Home Menu · 단독 사용 · 조합형", - tags: ["verification"], render: () => ( ( - - - -
{log => log}
-
- -
Figma 662:67267
-
- Figma 662:67331 최근파일 - Figma 662:67471 파일출력 2뎁스 -
-
-
- ), -} - // Property bar check (Figma 26:10492) against the current SWHeaderPropertyBar. Values are the Figma sample; the // bar itself is unchanged (3 differences, awaiting approval: home-menu-integration report §속성Bar). const barProperties: SWHeaderProperty[] = [ diff --git a/src/sw/sw-header.stories.tsx b/src/sw/sw-header.stories.tsx index 2babce6..04f7ae8 100644 --- a/src/sw/sw-header.stories.tsx +++ b/src/sw/sw-header.stories.tsx @@ -65,7 +65,7 @@ const callbacks = { const meta = { title: "SW/Header", - excludeStories: ["ComposedDemo"], + excludeStories: ["ComposedDemo", "PropertyPanelComparePage"], component: SWHeader, parameters: { layout: "fullscreen" }, args: { ...figmaArgs, ...callbacks }, @@ -289,6 +289,8 @@ function MotionSpecimen({ time }: { time?: number }) { export const WindowMoveMotion: Story = { name: "Window Move Motion", + // 2026-10-20 sidebar simplification: GIF frame verification; ID and direct URL kept. + tags: ["verification"], parameters: { controls: { disable: true } }, render: () => ( @@ -939,6 +941,8 @@ function usePropertyMenus(record: (line: string) => void, setProperties: (update export const KGuide: Story = { name: "K Guide", + // 2026-10-20 sidebar simplification: the same Header as Overview (K guide on hover); ID and direct URL kept. + tags: ["verification"], parameters: { controls: { disable: true } }, render: () =>
, } @@ -992,8 +996,7 @@ function PropertyCompare() {
} -export const PropertyPanelCompare: Story = { - name: "Property Panel · 4개 비교", - parameters: { controls: { disable: true } }, - render: () => , +/** Rendered by SW/Popup › Property Panel · 4개 비교 (sw-property-panel.stories.tsx, ID sw-header--property-panel-compare). */ +export function PropertyPanelComparePage() { + return } diff --git a/src/sw/sw-home-menu.css b/src/sw/sw-home-menu.css index c3837b9..a3d2c04 100644 --- a/src/sw/sw-home-menu.css +++ b/src/sw/sw-home-menu.css @@ -11,8 +11,5 @@ .sw-home-menu-story__table { border-collapse: collapse; font-size: 13px; } .sw-home-menu-story__table :is(th, td) { padding: 4px 8px; border: 1px solid #ccc; text-align: left; } .sw-home-menu-story__tall .sw-home-menu-story__frame { height: 860px; } -.sw-home-menu-story__figma-row { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 16px; margin-top: 12px; } -.sw-home-menu-story__figma-row > img { max-width: 100%; height: auto; } -.sw-home-menu-story__figma-fit { display: block; width: 100%; height: auto; margin-top: 12px; } .sw-home-menu-story__width { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; font-size: 13px; } .sw-home-menu-story__width input { width: min(480px, 60vw); } diff --git a/src/sw/sw-property-panel.stories.tsx b/src/sw/sw-property-panel.stories.tsx new file mode 100644 index 0000000..6661701 --- /dev/null +++ b/src/sw/sw-property-panel.stories.tsx @@ -0,0 +1,17 @@ +import type { Meta, StoryObj } from "@storybook/react-vite" +import { PropertyPanelComparePage } from "./sw-header.stories" + +const meta = { + title: "SW/Popup", + // 2026-10-20: moved from SW/Header to SW/Popup in the sidebar only; the id keeps sw-header--property-panel-compare + // for existing tests, documents and bookmarks. The file name sorts after sw-popup.stories.tsx, so this Story follows + // Custom Content and Multiple Popups. + id: "sw-header", + parameters: { layout: "fullscreen", controls: { disable: true } }, +} satisfies Meta +export default meta + +export const PropertyPanelCompare: StoryObj = { + name: "Property Panel · 4개 비교", + render: () => , +}