feat(sw): integrated improvement 0.2.0 (popup content, header open, tool buttons)
SW package 0.2.0 integrated improvement (Task A, steps 1-8). All new props are
optional; existing SW Stories are pixel-identical to the previous build (28/28).
- Build reproducibility: dist text normalized to LF, dist/build-info.json
(commit, dirty, tool versions, no timestamp), packages/sw/.gitattributes
(eol=lf). LF checkouts give identical dist and tarball.
- SWHeader: documentOpenPlacement ("menu" default | "header": Open right of
the logo in the existing document-button look, reusing onDocumentOpen and
documentOpenLabel, no duplicate Open in the dropdown), leading slot,
hiddenControls sub-items documentNew / documentOpen / layerFreeze /
layerLock. Open moves into More on measured overflow (with hysteresis).
- showNew / showOpen (SWHeaderDocumentTitle), showFreeze / showLock (layer
menu, field, property window list).
- SWToolButton (text / pill / document) and SWToolGroup (radio selection),
reusing the existing toggle, pill and file-name looks.
- SWPopup / SWPopupSection / SWPopupRow on the shared property window frame;
SWHeaderPropertyPanel gains children, title, autoFocus and optional
selection / properties / groups. Escape stack for several popups.
- Field dropdowns inside a popup use the shared fixed overlay
(useSWFixedDropdownPosition), so the scrolling body no longer clips them.
- AI guide, examples E/F, README, Storybook (SW/Header/Options, SW/Tool,
SW/Popup) and verification record docs/sw/sw-integrated-improvement-2026-10-19.md.
- Regression scripts rescoped for the intended changes (unused-removal 81/81,
overview 52/54 with the two pre-existing historical assertions).
Known limitation (unresolved): tools / leading content (incl. SWToolGroup)
does not move into More. With a wide tool bar the configured fields shrink
instead; in Example F the document name and layer field reach 0px at 390px.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5faa1f1ffe
commit
55179b4577
138 files changed
+17194
-162
No files matched your search
@@ -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 } from './storybook-inventory.mjs'
|
||||
import { swStoryEntries, retiredUnusedDemoIds, integratedStoryIds, integratedChangedFiles } 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'
|
||||
@@ -26,10 +26,12 @@ 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')
|
||||
check('inventory: 19 -> 10 SW Stories, 338 -> 329 total', beforeSW.length === 19 && afterSW.length === 10 && stories(beforeIndex).length === 338 && stories(afterIndex).length === 329, report.data.inventory)
|
||||
// 2026-10-19 integrated improvement: 329 + its 7 Stories under SW/Header/Options, SW/Tool and SW/Popup (SW/Header stays 10).
|
||||
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) })
|
||||
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))
|
||||
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: 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개 비교')
|
||||
@@ -44,9 +46,12 @@ const removedExports = ['PropertyFields', 'PropertyShapeSlot', 'Composition', 'C
|
||||
check('source: the nine Story exports are removed', removedExports.every(name => oldExports[name] && !newExports[name]))
|
||||
const changed = Object.keys(oldExports).filter(name => !removedExports.includes(name) && oldExports[name] !== newExports[name])
|
||||
check('source: retained exports (Stories and ComposedDemo) byte-identical', changed.length === 0 && Object.keys(newExports).every(name => oldExports[name]), changed)
|
||||
// The SW package may change only in the files of the 2026-10-19 integrated improvement (verified by its own suites);
|
||||
// other packages, Overview, Dropdown CSF, assets and Storybook config stay untouched.
|
||||
const untouched = ['packages/sw/src', 'packages/sw/ai', 'packages/sw/package.json', 'packages/sw/README.md', 'packages/ui', 'packages/org-chart', 'packages/org-chart-react', 'packages/center-graphic', 'src/sw/sw-header-overview.tsx', 'src/sw/sw-header-dropdown.stories.tsx', 'src/sw/sw-composed-controls.css', 'src/sw/assets', '.storybook']
|
||||
const diff = execFileSync('git', ['diff', '--name-only', baseCommit, '--', ...untouched], { encoding: 'utf8' }).trim()
|
||||
check('source: runtime, public API, AI template, other packages, Overview, Dropdown CSF, assets and Storybook config untouched', diff === '', diff)
|
||||
const diff = execFileSync('git', ['diff', '--name-only', baseCommit, '--', ...untouched], { encoding: 'utf8' }).trim().split(/\r?\n/).filter(Boolean)
|
||||
const unexpected = diff.filter(file => !integratedChangedFiles.includes(file))
|
||||
check('source: other packages, Overview, Dropdown CSF, assets and Storybook config untouched; SW package only within the integrated-improvement files', unexpected.length === 0, { unexpected, integrated: diff.length })
|
||||
|
||||
// ---- Browser
|
||||
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', '.gif': 'image/gif', '.ttf': 'font/ttf', '.woff2': 'font/woff2' }
|
||||
|
||||
Reference in new issue
Block a user