feat(sw): viewer header logo menu and file list; simplify SW Storybook
SW Viewer Header (approved optional props, public export names unchanged at 170): - SWViewerHeader: logoMenu, documents, activeDocumentId, onDocumentSelect, onDocumentOpen, documentOpenLabel; measured responsive toggles (full -> icons -> More) with the SWHeader More / file-list styling. - SW AI guides, ExampleH, viewer/text-weight/theme-inheritance tests and the logo-document-menu tests with their QA record. SW Storybook cleanup (Story IDs and test fixtures kept): - Sidebar: Overview -> "SW Header" (first), 전체 Footer -> "SW Footer", Footer/Viewer responsive pages -> "Responsive More", Viewer content-variants -> "Settings Popup" (merges the settings popup page). - Hidden by the verification tag (direct URL kept): Header Dropdown, Document Open, Interactive States, Document Dropdown, Hidden Sub Controls, Home Menu standalone; Footer tool groups / custom content / parts; SW/Theme; Viewer menu groups / item states / variable size / settings panel / Header + Dropdown. - Removed demo UI: Overview size and callback output (demo data and selection only with &verification), Home Menu Figma node table and width demo, Header Responsive More reduced to 1440 / 768 / 390, Popup reopen button, property-panel comparison captions, Viewer context-menu demo (&verification only). - Tests: storybook-inventory records the hidden and renamed Stories; overview / range-cross-browser / viewer open the demo controls with &verification; integrated-popup reloads the Story instead of the reopen button; dropdown-consolidation asserts Dropdown is hidden from the sidebar and still opens by its direct URL.
This commit is contained in:
1 parent
46119eacb5
commit
23d522c136
57 files changed
+2623
-333
No files matched your search
@@ -1,7 +1,8 @@
|
||||
// 2026-10-20 SW text weight request: Bold only on the named texts, with the black text outline where asked.
|
||||
// Header file name (700) · Composed Controls field values (700) vs SWHeader field values (400) · Footer 보조기능 / 명령어
|
||||
// titles and category tabs (700, 전체보기 / Model · Layout / commands unchanged) · Viewer header file name, labels and
|
||||
// Model / Layout tabs (700, More kept) · recent files name / path / preview title (700 + outline). Hover keeps the
|
||||
// Model / Layout tabs (700, More kept; 2026-10-21 logo menu and sample list follow the SWHeader `...` menu / file-name
|
||||
// list rules) · recent files name / path / preview title (700 + outline). Hover keeps the
|
||||
// text in place. Usage: build Storybook first, then node packages/sw/tests/text-weight.browser.mjs [evidence-dir]
|
||||
import { readFile, writeFile, mkdir } from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
@@ -109,19 +110,61 @@ check('Footer: ◀ ▶ only when the categories overflow their area', (area.cont
|
||||
await page.screenshot({ path: path.join(out, 'footer.png'), clip: { x: 0, y: 940, width: 1920, height: 160 } })
|
||||
|
||||
// ---------- 3. Viewer header ----------
|
||||
// 2026-10-21 (approved restructure): 파일 열기 moved into the logo menu (the SWHeader `...` menu, SWHeaderMore), 샘플 into
|
||||
// the file-name list (SWHeaderDocumentTitle) and 전체 보기 into More. The header keeps the Bold file name (now the
|
||||
// SWHeader file-name button), 레이어 · 설정 · 속성 and Model / Layout; the two menus follow the SWHeader rules, measured
|
||||
// on SWHeader itself below and compared row by row.
|
||||
const typo = s => ({ weight: s.weight, size: s.size, family: s.family, outline: s.outline })
|
||||
// SWHeader references: the responsive `...` menu rows and the file-name list rows.
|
||||
await goto('sw-header--responsive-more')
|
||||
const refTrigger = page.locator('.hm-sw-header__more-trigger').filter({ visible: true }).first()
|
||||
await refTrigger.click(); await page.waitForTimeout(200)
|
||||
const refMore = await styles('.hm-sw-header__more-menu .hm-sw-header__more-item > span:first-child')
|
||||
check('SWHeader ... menu rows (reference): Regular 400 without outline', refMore.length > 0 && refMore.every(r => r.weight === '400' && r.outline === 'none'), refMore)
|
||||
await page.keyboard.press('Escape')
|
||||
await goto('sw-header--document-dropdown')
|
||||
await page.locator('.hm-sw-header__document-button').first().click(); await page.waitForTimeout(200)
|
||||
const refDocs = await styles('.hm-sw-header__document-menu .hm-sw-header__document-item-name')
|
||||
check('SWHeader file-name list rows (reference): 14px + 1.3px outline, one weight', refDocs.length > 0 && refDocs.every(r => r.size === '14px' && r.outline === OUTLINE_14 && r.weight === refDocs[0].weight), refDocs)
|
||||
// 2026-10-21: the logo menu takes the viewer dropdown type (SWViewerMenu, "상단 메뉴 + Dropdown"); its rows and label are the reference.
|
||||
await goto('sw-viewer--dropdowns')
|
||||
await page.getByRole('button', { name: '도면' }).click(); await page.waitForTimeout(200)
|
||||
const refViewerItem = await styles('.hm-sw-viewer-menu .hm-sw-viewer-menu__text')
|
||||
const refViewerLabel = await styles('.hm-sw-viewer-menu .hm-sw-viewer-menu__label')
|
||||
check('SWViewerMenu rows / label (reference): 14px 400 and 12px 500, no outline', refViewerItem.length > 0 && refViewerItem.every(r => r.size === '14px' && r.weight === '400' && r.outline === 'none')
|
||||
&& refViewerLabel.length > 0 && refViewerLabel.every(r => r.size === '12px' && r.weight === '500' && r.outline === 'none'), { refViewerItem: refViewerItem.slice(0, 2), refViewerLabel })
|
||||
await page.keyboard.press('Escape')
|
||||
report.reference = { more: refMore[0], documents: refDocs[0], viewerItem: refViewerItem[0], viewerLabel: refViewerLabel[0] }
|
||||
|
||||
await goto('sw-viewer--viewer-header')
|
||||
// The 1440px Story frame at full width (as the viewer suites): the header has room for every label.
|
||||
await page.addStyleTag({ content: '.sb-page { --sb-page-max-width: 100vw; }' }); await page.waitForTimeout(200)
|
||||
const vh = page.locator('.hm-sw-viewer-header').first()
|
||||
const vNames = await styles('.hm-sw-viewer-header >> nth=0 >> :is(.hm-sw-viewer-header__document-name, .hm-sw-viewer-header__label, .hm-sw-viewer-header__tab)')
|
||||
const vNames = await styles('.hm-sw-viewer-header >> nth=0 >> :is(.hm-sw-header__document-name, .hm-sw-viewer-header__document-name, .hm-sw-viewer-header__label, .hm-sw-viewer-header__tab)')
|
||||
report.viewer = vNames
|
||||
const want = ['파일 열기', '샘플', '전체 보기', '레이어', '설정', '속성']
|
||||
// 2026-10-21 measured steps: at 1440 the header has room, so 전체 보기 is a header label again (Bold like the others), and
|
||||
// the file open button after the logo shows 파일 열기 on the SWHeader file-name surface (Bold + outline like the file name).
|
||||
const want = ['C0060202-001-평면및종단면도.dwg', '파일 열기', '전체 보기', '레이어', '설정', '속성']
|
||||
const labels = vNames.map(v => v.text)
|
||||
check('Viewer: file name, 파일열기 · 샘플 · 전체보기 · 레이어 · 설정 · 속성, Model · Layout are 14px 700 + 1.3px outline', want.every(w => labels.includes(w)) && labels.some(t => t.startsWith('Model')) && labels.some(t => t.startsWith('Layout')) && vNames.every(v => v.weight === '700' && v.size === '14px' && v.outline === OUTLINE_14), vNames)
|
||||
check('Viewer: file name, 파일 열기, 전체 보기 · 레이어 · 설정 · 속성, Model · Layout are 14px 700 + 1.3px outline', want.every(w => labels.includes(w)) && labels.some(t => t.startsWith('Model')) && labels.some(t => t.startsWith('Layout')) && vNames.every(v => v.weight === '700' && v.size === '14px' && v.outline === OUTLINE_14), vNames)
|
||||
check('Viewer: 샘플 is no longer a header label', !labels.includes('샘플'), labels)
|
||||
const counts = await styles('.hm-sw-viewer-header >> nth=0 >> .hm-sw-viewer-header__count')
|
||||
check('Viewer: tab counts keep 11px 400', counts.length > 0 && counts.every(c => c.weight === '400' && c.size === '11px'), counts)
|
||||
for (const t of ['파일 열기', '레이어']) {
|
||||
const lab = vh.locator('.hm-sw-viewer-header__label', { hasText: t }).first()
|
||||
await stableOnHover(`Viewer ${t}`, lab.locator('xpath=ancestor::button[1]'), lab)
|
||||
}
|
||||
// File open button (파일 열기, the logo menu is gone): hover keeps its label in place, size and weight.
|
||||
const openButton = vh.locator('[data-document-open]')
|
||||
await stableOnHover('Viewer 파일 열기', openButton, openButton.locator('.hm-sw-viewer-header__open-label'))
|
||||
// File-name list (샘플): rows exactly as the SWHeader file-name list rows.
|
||||
const docButton2 = vh.locator('.hm-sw-viewer-header__document .hm-sw-header__document-button')
|
||||
await stableOnHover('Viewer file name', docButton2, docButton2.locator('.hm-sw-header__document-name'))
|
||||
await docButton2.click(); await page.waitForTimeout(150)
|
||||
const sampleRows = await styles('.hm-sw-viewer-header >> nth=0 >> .hm-sw-header__document-item-name')
|
||||
report.viewerSamples = sampleRows
|
||||
check('Viewer sample list: 3 rows = SWHeader file-name list rows (weight / size / family / outline)', sampleRows.length === 3 && sampleRows.every(r => JSON.stringify(typo(r)) === JSON.stringify(typo(refDocs[0])) && !r.cut), { sampleRows, ref: refDocs[0] })
|
||||
const sampleRow = vh.locator('.hm-sw-header__document-item').first()
|
||||
await stableOnHover('Viewer sample row', sampleRow, sampleRow.locator('.hm-sw-header__document-item-name'))
|
||||
await page.keyboard.press('Escape'); await page.waitForTimeout(100)
|
||||
const lab = vh.locator('.hm-sw-viewer-header__label', { hasText: '레이어' }).first()
|
||||
await stableOnHover('Viewer 레이어', lab.locator('xpath=ancestor::button[1]'), lab)
|
||||
const tab = vh.locator('.hm-sw-viewer-header__tab', { hasText: 'Layout' }).first()
|
||||
await stableOnHover('Viewer Layout tab', tab, tab)
|
||||
// More stays: narrow header shows the More button, it opens and lists the moved items.
|
||||
|
||||
Reference in new issue
Block a user