feat(sw): add independent viewer header face tokens

This commit is contained in:
shkim4 committed 2026-11-10 17:51:47 +09:00
1 parent 65fa928694
commit f61d181bb1
5 files changed
+79 -16

No files matched your search

@@ -230,6 +230,50 @@ async function dropdownColors(page, def, themed) {
await header.close()
}
// ---------- 1c. Viewer Header (2026-11-10): --hm-sw-viewer-document-* / -object-* / -property-* face aliases ----------
// Shared by default (an SWHeader theme on the outermost SW scope reaches the viewer faces); a --hm-sw-viewer-* value there
// changes the Viewer Header faces alone and leaves SWHeader and the Step Header as they are.
{
const setOn = (page, root, values) => page.locator(root).first().evaluate((element, values) => {
let outer = element
for (let e = element; e; e = e.parentElement) if (e.matches?.('.hm-sw-header, .hm-sw-theme')) outer = e
Object.entries(values).forEach(([token, value]) => value === null ? outer.style.removeProperty(token) : outer.style.setProperty(token, value))
}, values)
const page = await newPage()
await open(page, 'sw-viewer--viewer-header')
const read = () => page.evaluate(() => {
// Every match (the Story has more than one header; some file-name areas carry no face of their own).
const paint = selector => { const all = [...document.querySelectorAll(selector)]; if (!all.length) return null; return all.map(e => { const s = getComputedStyle(e); return `${s.backgroundColor} ${s.backgroundImage}` }).join(' || ') }
// The document face token paints the trailing status / button strip segments in this Story.
return { document: paint('.hm-sw-viewer-header__actions > :is(.hm-sw-viewer-status, .hm-sw-viewer-header__button, .hm-sw-header__window-buttons)'), property: paint('.hm-sw-viewer-header__group[data-surface="field"]') }
})
const A = 'linear-gradient(rgb(44, 55, 66), rgb(44, 55, 66))', B = 'linear-gradient(rgb(1, 2, 3), rgb(1, 2, 3))'
const base = await read()
await setOn(page, '.hm-sw-viewer-header', { '--hm-sw-header-document-background': A, '--hm-sw-header-property-background': A })
const inherited = await read()
check('Viewer Header: 바깥 범위의 SWHeader 토큰(파일명·속성 면)이 그대로 전달', base.document !== null && base.property !== null && inherited.document.includes('rgb(44, 55, 66)') && inherited.property.includes('rgb(44, 55, 66)'), JSON.stringify({ base, inherited }))
await setOn(page, '.hm-sw-viewer-header', { '--hm-sw-viewer-document-background': B, '--hm-sw-viewer-property-background': B })
const own = await read()
check('Viewer Header: --hm-sw-viewer-* 지정이 SWHeader 토큰보다 우선', own.document.includes('rgb(1, 2, 3)') && own.property.includes('rgb(1, 2, 3)'), JSON.stringify(own))
await setOn(page, '.hm-sw-viewer-header', { '--hm-sw-header-document-background': null, '--hm-sw-header-property-background': null, '--hm-sw-viewer-document-background': null, '--hm-sw-viewer-property-background': null })
check('Viewer Header: 지정을 지우면 기본값으로 복귀', JSON.stringify(await read()) === JSON.stringify(base), JSON.stringify(base))
await page.close()
// The Viewer Header face tokens on SWHeader and Step Header pages change nothing there.
const names = ['document-background', 'document-border-gradient', 'document-border-color', 'object-background', 'object-border-gradient', 'object-radius', 'property-background', 'property-border-color', 'property-radius', 'property-shadow']
const values = Object.fromEntries(names.map(name => [`--hm-sw-viewer-${name}`, name.endsWith('radius') ? '9px' : name.endsWith('shadow') ? '0 0 0 3px rgb(1, 2, 3)' : name.endsWith('color') ? 'rgb(1, 2, 3)' : B]))
const untouched = []
for (const [id, root] of [['sw-header--overview', '.hm-sw-header'], ['sw-step-header--process-header', '.hm-sw-process-header']]) {
const other = await newPage()
await open(other, id)
const paint = () => other.evaluate(root => [...document.querySelectorAll(`${root}, ${root} *`)].map(element => { const s = getComputedStyle(element); return `${s.color}|${s.backgroundColor}|${s.backgroundImage}|${s.boxShadow}|${s.borderTopColor}|${s.borderTopLeftRadius}` }).join('\n'), root)
const before = await paint()
await setOn(other, root, values)
untouched.push(`${id} ${before === await paint() ? 'same' : 'CHANGED'} ${before.split('\n').length}`)
await other.close()
}
check('Viewer Header 토큰은 SWHeader·Step Header 화면에 영향 없음', untouched.every(item => item.includes(' same ')), untouched.join(', '))
}
// ---------- 2. Regression: new cascade vs legacy cascade on every existing SW Story ----------
const here = path.dirname(fileURLToPath(import.meta.url))
const outermost = ':is(.hm-sw-header, .hm-sw-theme):not(:where(.hm-sw-header, .hm-sw-theme) *)'