refactor(storybook): fold SW Header Options stories into SW/Header
Remove the separate SW/Header/Options sidebar item. Its examples move to two
Stories directly under SW/Header (src/sw/sw-header-open.stories.tsx):
- Document Open: Open placement, label, 10-width responsive, composed bar,
composed (controls) responsive
- Hidden Sub Controls: document New / Open and layer freeze / lock removal
No public API or component change. Tests and inventory follow the new IDs
(integrated 97/97, existing Stories pixel-identical 28/28, unused-removal
83/83). The two remaining overview failures are pre-existing historical
assertions (also failing on 5faa1f1), not new defects.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
55179b4577
commit
e8409eff44
17 files changed
+168
-87
No files matched your search
@@ -33,7 +33,7 @@ const log = () => page.locator('[data-callback-log]').first().textContent()
|
||||
const rect = locator => locator.evaluate(e => { const r = e.getBoundingClientRect(); return { x: r.x, y: r.y, w: r.width, h: r.height, right: r.right } })
|
||||
|
||||
if (sections.includes('options')) {
|
||||
await goto('sw-header-options--open-placement')
|
||||
await goto('sw-header--document-open')
|
||||
const frames = page.locator('.sw-story-frame')
|
||||
// Default placement unchanged: no header Open, dropdown footer keeps + New / Open.
|
||||
const plain = frames.nth(0).locator('header.hm-sw-header')
|
||||
@@ -63,7 +63,7 @@ if (sections.includes('options')) {
|
||||
await page.keyboard.press('Escape')
|
||||
await open.click()
|
||||
check('header: Open calls onDocumentOpen', (await log()).includes('onDocumentOpen'))
|
||||
check('documentOpenLabel is the Open text', await frames.nth(2).locator('[data-document-open]').textContent() === '파일 열기')
|
||||
check('documentOpenLabel is the Open text', await page.locator('[data-open-label] [data-document-open]').textContent() === '파일 열기')
|
||||
|
||||
// Responsive: measured room. No overflow anywhere; Open is either shown or reachable in More.
|
||||
const widths = []
|
||||
@@ -106,7 +106,7 @@ if (sections.includes('options')) {
|
||||
const flips = trace.slice(1).filter((step, index) => step[1] !== trace[index][1]).length
|
||||
check('resize: collapsed Open returns once when the header grows (measured, with hysteresis)', trace[0][1] === 0 && trace.at(-1)[1] === 1 && flips === 1, trace)
|
||||
|
||||
await goto('sw-header-options--hidden-sub-controls')
|
||||
await goto('sw-header--hidden-sub-controls')
|
||||
const onlyOpen = page.locator('[data-hidden="new"] .hm-sw-header__document-footer')
|
||||
const footer = await rect(onlyOpen), action = await rect(onlyOpen.locator('.hm-sw-header__document-action'))
|
||||
check('hidden documentNew: footer keeps Open on its right side', JSON.stringify(await onlyOpen.locator('.hm-sw-header__document-action').allTextContents()) === '["Open"]' && Math.abs(footer.right - 8 - action.right) < 1, { footer, action })
|
||||
@@ -121,7 +121,7 @@ if (sections.includes('options')) {
|
||||
await page.locator('[data-hidden="layer-states"]').screenshot({ path: path.join(out, 'hidden-layer-states.png') })
|
||||
await page.locator('[data-hidden="new"]').screenshot({ path: path.join(out, 'hidden-document-new.png') })
|
||||
|
||||
await goto('sw-header-options--composed-open')
|
||||
await goto('sw-header--document-open')
|
||||
const bar = page.locator('[data-composed-open]')
|
||||
const cHome = await rect(bar.locator('.hm-sw-header__home')), cOpen = await rect(bar.locator('.hm-sw-header__document[data-tool] button')), cDoc = bar.locator('.hm-sw-header__document:not([data-tool]) .hm-sw-header__document-button')
|
||||
check('composed: Open right of the logo at the same junction offset as SWHeader', Math.abs(cOpen.x - cHome.right - report.data.junction) < 0.6 && cOpen.h === 48, { cHome, cOpen })
|
||||
@@ -135,7 +135,7 @@ if (sections.includes('options')) {
|
||||
}
|
||||
|
||||
if (sections.includes('options') || sections.includes('composed')) {
|
||||
await goto('sw-header-options--composed-responsive')
|
||||
await goto('sw-header--document-open')
|
||||
const rows = []
|
||||
for (const item of await page.locator('[data-composed-responsive] > [data-width]').all()) {
|
||||
const width = Number(await item.getAttribute('data-width'))
|
||||
|
||||
@@ -10,13 +10,16 @@ export const swStoryEntries = index => Object.values(index.entries).filter(entry
|
||||
export const retainedInventory = entries => entries.filter(entry => ![...retiredStage1Ids, ...retiredDropdownIds].includes(entry.id))
|
||||
.map(entry => entry.id === 'sw-header--composed-controls' ? { ...entry, name: 'Dropdown', title: 'SW/Header' } : entry)
|
||||
export const inventorySignature = entries => entries.map(entry => [entry.id, entry.name, entry.tags]).sort((a, b) => a[0].localeCompare(b[0]))
|
||||
// 2026-10-19 SW integrated improvement (0.2.0): the only Stories added after the unused-demo removal, under their
|
||||
// own titles (SW/Header keeps its 10 Stories), and the only files of the package it changed.
|
||||
export const integratedStoryIds = ['sw-header-options--open-placement', 'sw-header-options--hidden-sub-controls', 'sw-header-options--composed-open', 'sw-header-options--composed-responsive', 'sw-tool--tool-buttons', 'sw-popup--custom-content', 'sw-popup--multiple-popups']
|
||||
// 2026-10-19 SW integrated improvement (0.2.0): the only Stories added after the unused-demo removal (two under
|
||||
// SW/Header next to its 10 retained Stories, the rest under SW/Tool and SW/Popup), and the only package files it changed.
|
||||
// The two Header Stories sit directly under SW/Header (no separate Options menu), in src/sw/sw-header-open.stories.tsx.
|
||||
export const integratedStoryIds = ['sw-header--document-open', 'sw-header--hidden-sub-controls', 'sw-tool--tool-buttons', 'sw-popup--custom-content', 'sw-popup--multiple-popups']
|
||||
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',
|
||||
'packages/sw/ai/examples/ExampleE-CustomPopup.tsx', 'packages/sw/ai/examples/ExampleF-ViewerToolbar.tsx',
|
||||
'packages/sw/src/index.ts', 'packages/sw/src/theme/sw.css',
|
||||
'packages/sw/src/components/sw-popup/SWPopup.tsx', 'packages/sw/src/components/sw-tool/SWTool.tsx',
|
||||
'packages/sw/src/components/sw-header/SWHeader.tsx', 'packages/sw/src/components/sw-header/index.ts', 'packages/sw/src/components/sw-header/types.ts',
|
||||
...['SWHeaderDocumentTitle', 'SWHeaderDropdown', 'SWHeaderFields', 'SWHeaderLayerMenu', 'SWHeaderLineStyleMenu', 'SWHeaderMore', 'SWHeaderPropertyFields', 'SWHeaderPropertyPanel'].map(name => `packages/sw/src/components/sw-header/components/${name}.tsx`),
|
||||
]
|
||||
@@ -26,12 +26,13 @@ const beforeSW = swStoryEntries(beforeIndex), afterSW = swStoryEntries(afterInde
|
||||
const expected = beforeSW.filter(e => !retiredUnusedDemoIds.includes(e.id))
|
||||
report.data.inventory = { before: [stories(beforeIndex).length, beforeSW.length], after: [stories(afterIndex).length, afterSW.length], sw: afterSW.map(e => [e.id, e.name]) }
|
||||
await writeFile(path.join(out, 'story-inventory-after.json'), JSON.stringify({ total: stories(afterIndex).length, sw: afterSW.map(e => ({ id: e.id, name: e.name, title: e.title, tags: e.tags })) }, null, 2) + '\n')
|
||||
// 2026-10-19 integrated improvement: 329 + its 7 Stories under SW/Header/Options, SW/Tool and SW/Popup (SW/Header stays 10).
|
||||
// 2026-10-19 integrated improvement: 329 + its 5 Stories (2 under SW/Header, SW/Tool, SW/Popup); the 10 retained SW/Header Stories stay.
|
||||
const added = stories(afterIndex).filter(e => !beforeIndex.entries[e.id])
|
||||
check('inventory: 19 -> 10 SW/Header Stories, 338 -> 329 total plus only the 7 integrated-improvement Stories', beforeSW.length === 19 && afterSW.length === 10 && stories(beforeIndex).length === 338 && stories(afterIndex).length === 329 + integratedStoryIds.length && JSON.stringify(added.map(e => e.id).sort()) === JSON.stringify([...integratedStoryIds].sort()), { ...report.data.inventory, added: added.map(e => e.id) })
|
||||
const retainedSW = afterSW.filter(e => !integratedStoryIds.includes(e.id))
|
||||
check('inventory: 19 -> 10 retained SW/Header Stories, 338 -> 329 total plus only the integrated-improvement Stories', beforeSW.length === 19 && retainedSW.length === 10 && stories(beforeIndex).length === 338 && stories(afterIndex).length === 329 + integratedStoryIds.length && JSON.stringify(added.map(e => e.id).sort()) === JSON.stringify([...integratedStoryIds].sort()), { ...report.data.inventory, added: added.map(e => e.id) })
|
||||
check('inventory: the nine requested IDs existed before and are absent now', retiredUnusedDemoIds.length === 9 && retiredUnusedDemoIds.every(id => beforeIndex.entries[id] && !afterIndex.entries[id]))
|
||||
check('inventory: retained SW IDs, names, titles, tags and order unchanged', sig(expected) === sig(afterSW), afterSW.map(e => e.id))
|
||||
const others = index => Object.values(index.entries).filter(e => !retiredUnusedDemoIds.includes(e.id) && !integratedStoryIds.includes(e.id) && !/^sw-(header-options|tool|popup)--docs$/.test(e.id))
|
||||
check('inventory: retained SW IDs, names, titles, tags and order unchanged', sig(expected) === sig(retainedSW), retainedSW.map(e => e.id))
|
||||
const others = index => Object.values(index.entries).filter(e => !retiredUnusedDemoIds.includes(e.id) && !integratedStoryIds.includes(e.id) && !/^sw-(tool|popup)--docs$/.test(e.id))
|
||||
check('inventory: every non-removed index entry identical (docs and other packages included)', JSON.stringify(others(beforeIndex)) === JSON.stringify(others(afterIndex)))
|
||||
check('inventory: Dropdown keeps sw-header--composed-controls / Dropdown / SW/Header', afterIndex.entries['sw-header--composed-controls']?.name === 'Dropdown' && afterIndex.entries['sw-header--composed-controls']?.title === 'SW/Header')
|
||||
check('inventory: comparison keeps its ID and name', afterIndex.entries['sw-header--property-panel-compare']?.name === 'Property Panel · 4개 비교')
|
||||
|
||||
Reference in new issue
Block a user