feat(sw): viewer layer bulb, popup toggle switch, footer layout and 1440px story inner
Deploy Storybook / deploy (push) Successful in 1m11s

- SW Viewer layer popup: search + 전체 레이어 fixed, only the list scrolls; the all-layers
  control is the SWLayerVisibilityIcon bulb (role="switch"), one light #d2c8b4 line under it.
- Example H and the layer popup AI docs follow the bulb layout (VIEWER, DESIGN_RULES,
  COMPONENT_CATALOG, COMPOSITION_PATTERNS, AI_GUIDE sync).
- Popup toggle switch (Figma toggle_btn_new 633:75188 / 633:75902): one sw.css face for the
  HM UI Switch in SWPopup and SWViewerSwitch in SWViewerPanel; SW Header switches unchanged.
- SW Footer stories: no inner scrollers, fluid screens; workspace fits the viewport.
- SW Footer category tabs keep their positions when selected (divider slots kept, pocket
  edges drawn over the neighbours' padding).
- Storybook .sb-page-inner: 1440px max from 1920px (was 80vw).
- SW Header equal-split change was cancelled; header CSS unchanged.

Verified: check:ai-docs PASS, viewer test 49 PASS (1 FAIL hover face + timeout pre-existing),
footer-design-review 21 PASS, browser checks of switch/footer/inner.
Not verified: footer-popup-viewer-refinement (needs full Storybook build), text-weight/hover
tests, Switch 37x16 AI docs (deferred).
This commit is contained in:
shkim4 committed 2026-10-22 20:20:00 +09:00
1 parent 258e0a4b68
commit c1549b2b4f
22 files changed
+121 -63

No files matched your search

@@ -321,7 +321,8 @@ export const SWFooterMenu = forwardRef<HTMLDivElement, SWFooterMenuProps>(functi
const selected = item.id === current
const previousSelected = index > 0 && items[index - 1].id === current
return [
index > 0 && !selected && !previousSelected && <span key={`${item.id}:divider`} className="hm-sw-footer-menu__divider" aria-hidden="true" />,
// 2026-10-22: the divider slot stays next to the current tab (hidden) so selecting never moves a tab.
index > 0 && <span key={`${item.id}:divider`} className="hm-sw-footer-menu__divider" data-pocket={selected || previousSelected || undefined} aria-hidden="true" />,
<button key={item.id} type="button" role="tab" id={`${prefix}-${item.id}`} className="hm-sw-footer-menu__tab"
aria-selected={selected} aria-controls={panelId} tabIndex={item.id === roving ? 0 : -1} disabled={item.disabled}
onClick={() => { if (!selected) onValueChange?.(item.id) }}>
@@ -340,7 +341,7 @@ export const SWFooterMenu = forwardRef<HTMLDivElement, SWFooterMenuProps>(functi
</button>,
]}
{onAdd && [
!steps && items.length > 0 && items[items.length - 1].id !== current && <span key="add:divider" className="hm-sw-footer-menu__divider" aria-hidden="true" />,
!steps && items.length > 0 && <span key="add:divider" className="hm-sw-footer-menu__divider" data-pocket={items[items.length - 1].id === current || undefined} aria-hidden="true" />,
<button key="add" type="button" className="hm-sw-footer-menu__add" aria-label={addLabel} title={addLabel} onClick={onAdd} />,
]}
</div>
@@ -11,8 +11,8 @@ export interface SWViewerSwitchProps extends Omit<ButtonHTMLAttributes<HTMLButto
}
/**
* 36 x 20 switch. Its face follows where it is placed: dark header face (off #0A221D, on #FFC600) inside
* SWViewerHeader, beige panel face (off #9A9284, on #266651) inside SWViewerPanel.
* Switch. Its face follows where it is placed: dark header face (36 x 20, off #0A221D, on #FFC600) inside
* SWViewerHeader, the SW popup toggle face (37 x 16, Figma toggle_btn_new, sw.css) inside SWViewerPanel.
*/
export const SWViewerSwitch = forwardRef<HTMLButtonElement, SWViewerSwitchProps>(function SWViewerSwitch(
{ checked, onCheckedChange, className, onClick, ...rest }, ref,