feat(sw): viewer layer bulb, popup toggle switch, footer layout and 1440px story inner
Deploy Storybook / deploy (push) Successful in 1m11s
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:
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,
|
||||
|
||||
@@ -394,8 +394,11 @@
|
||||
.hm-sw-footer-menu__tab:is(:hover:not(:disabled), [aria-selected="true"]) { color: var(--hm-sw-footer-accent); }
|
||||
/* 1px × 10px black divider (Rectangle 7480 …) between tabs; the current tab has its 7px pocket edges instead. */
|
||||
.hm-sw-footer-menu__divider { position: relative; flex: 0 0 1px; width: 1px; height: 10px; margin-top: 7px; background: var(--hm-sw-footer-menu-divider); }
|
||||
.hm-sw-footer-menu__tab[aria-selected="true"] { margin-right: 7px; }
|
||||
.hm-sw-footer-menu__tab[aria-selected="true"]:not(:first-of-type) { margin-left: 7px; }
|
||||
/* 2026-10-22: selecting a tab never moves text or tabs. The row keeps every 1px divider slot (hidden beside the
|
||||
current tab) and the current tab gets no margins: its 7px pocket edges are drawn over the neighbours' 8px padding.
|
||||
The last tab always keeps 6px on its right so its pocket edge (6px + the 1px slot) stays clear of + / ◀ ▶. */
|
||||
.hm-sw-footer-menu__divider[data-pocket] { visibility: hidden; }
|
||||
.hm-sw-footer-menu__tab:last-of-type { margin-right: 6px; }
|
||||
.hm-sw-footer-menu__add { position: relative; flex: 0 0 28px; width: 28px; height: 12px; margin-top: 6px; background: url("../components/sw-footer/assets/menu-add.svg") 0 0 / 28px 12px no-repeat; }
|
||||
/* Not in Figma: only Default of btn_add (26:9451) exists. Hover (2026-10-20, user request): the + in the footer accent
|
||||
(#FF5C00, same black outline), like the category tabs next to it. */
|
||||
|
||||
@@ -490,9 +490,7 @@ button.hm-sw-viewer-header__brand { text-align: left; }
|
||||
.hm-sw-viewer-switch[data-state="checked"] { background: var(--hm-sw-viewer-switch-on); }
|
||||
.hm-sw-viewer-switch[data-state="checked"] .hm-sw-viewer-switch__thumb { transform: translateX(16px); background: var(--hm-sw-viewer-switch-thumb-on); }
|
||||
.hm-sw-theme .hm-sw-viewer-switch:disabled { opacity: var(--hm-sw-viewer-disabled-opacity); cursor: not-allowed; }
|
||||
.hm-sw-viewer-panel .hm-sw-viewer-switch { background: var(--hm-sw-viewer-panel-switch-off); box-shadow: none; }
|
||||
.hm-sw-viewer-panel .hm-sw-viewer-switch .hm-sw-viewer-switch__thumb { background: #fff; }
|
||||
.hm-sw-viewer-panel .hm-sw-viewer-switch[data-state="checked"] { background: var(--hm-sw-viewer-panel-switch-on); }
|
||||
/* Panel switches: the SW popup toggle face in sw.css (Figma toggle_btn_new, 2026-10-22). */
|
||||
@media (prefers-reduced-motion: reduce) { .hm-sw-viewer-switch, .hm-sw-viewer-switch__thumb { transition: none; } }
|
||||
|
||||
/* ---------- Dropdown ---------- */
|
||||
|
||||
@@ -88,6 +88,13 @@
|
||||
--hm-sw-property-label: #000;
|
||||
--hm-sw-property-table: #d2c8b4;
|
||||
--hm-sw-property-inner-border: #948871;
|
||||
/* Popup toggle switch (Figma 이지빔-SW toggle_btn_new: off 633:75188, on 633:75902, 2026-10-22). */
|
||||
--hm-sw-switch-off-background: #c7bda9;
|
||||
--hm-sw-switch-off-border: #8a7b5e;
|
||||
--hm-sw-switch-on-background: #f7efdf;
|
||||
--hm-sw-switch-on-border: #d2570b;
|
||||
--hm-sw-switch-thumb-off: linear-gradient(180deg, #fbedd4 0%, #eee3da 100%);
|
||||
--hm-sw-switch-thumb-on: linear-gradient(180deg, #e8741e 0%, #c0520d 100%);
|
||||
/* Popup scrollbar (every SW popup body: SWPopup, SWViewerPanel, property window). Same as the DWG/DXF viewer
|
||||
panels (thin, HM warm-neutral-mid thumb on warm-neutral-light track). */
|
||||
--hm-sw-popup-scrollbar-thumb: #9a9284;
|
||||
@@ -1590,6 +1597,31 @@ div.hm-sw-header__menu-row { justify-content: space-between; gap: 8px; padding-l
|
||||
.hm-sw-property__body { display: flex; flex-direction: column; gap: 8px; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 7px 7px 7px; box-shadow: inset 0 2px 2px rgba(255,255,255,.6); }
|
||||
/* Popup scrollbar: the body and any scrolling area inside it (zero-specificity so content can still override). */
|
||||
.hm-sw-property__body, .hm-sw-property__body :where(*) { scrollbar-width: thin; scrollbar-color: var(--hm-sw-popup-scrollbar-thumb) var(--hm-sw-popup-scrollbar-track); }
|
||||
/* Popup toggle switch (Figma toggle_btn_new 633:75188 / 633:75902): one face for every switch inside an SW popup —
|
||||
the HM UI Switch in SWPopup and SWViewerSwitch in SWViewerPanel (both carry .hm-sw-property). SW Header switches
|
||||
are outside this scope and keep their own face. 37 x 16 track, 12 x 12 thumb 2px from the edge; the border is an
|
||||
inset ring so off (1px) and on (0.8px) keep the same geometry. Disabled / focus: not in Figma, the owners' rules
|
||||
(opacity, cursor) stay; the focus outline uses the on border color because the ring shadow is replaced. */
|
||||
.hm-sw-property [role="switch"]:is([data-slot="switch"], .hm-sw-viewer-switch) {
|
||||
box-sizing: border-box; display: inline-flex; align-items: center; flex-shrink: 0;
|
||||
width: 37px; height: 16px; padding: 0; border: 0; border-radius: 100px;
|
||||
background: var(--hm-sw-switch-off-background);
|
||||
box-shadow: inset 1px 0 2px rgba(0, 0, 0, .3), inset 0 2px 2px rgba(0, 0, 0, .3), inset 0 0 0 1px var(--hm-sw-switch-off-border), 1px 1px 1px #fcf0d8;
|
||||
}
|
||||
.hm-sw-property [role="switch"]:is([data-slot="switch"], .hm-sw-viewer-switch)[data-state="checked"] {
|
||||
background: var(--hm-sw-switch-on-background);
|
||||
box-shadow: inset 1px 0 1px 1px rgba(0, 0, 0, .2), inset 0 1px 1px 1px rgba(0, 0, 0, .2), inset 0 0 0 .8px var(--hm-sw-switch-on-border), 1px 1px 1px #fcf0d8;
|
||||
}
|
||||
.hm-sw-property [role="switch"]:is([data-slot="switch"], .hm-sw-viewer-switch):hover:not(:disabled) { background-image: none; }
|
||||
.hm-sw-property [role="switch"]:is([data-slot="switch"], .hm-sw-viewer-switch):focus-visible { outline: 2px solid var(--hm-sw-switch-on-border); outline-offset: 1px; }
|
||||
.hm-sw-property [role="switch"] > :is([data-slot="switch-thumb"], .hm-sw-viewer-switch__thumb) {
|
||||
width: 12px; height: 12px; border-radius: 6.5px;
|
||||
background: var(--hm-sw-switch-thumb-off); box-shadow: 0 .5px 1px rgba(0, 0, 0, .6);
|
||||
transform: translateX(2px);
|
||||
}
|
||||
.hm-sw-property [role="switch"][data-state="checked"] > :is([data-slot="switch-thumb"], .hm-sw-viewer-switch__thumb) {
|
||||
background: var(--hm-sw-switch-thumb-on); transform: translateX(23px);
|
||||
}
|
||||
.hm-sw-property[data-selection-kind="all"] .hm-sw-property__body { padding-bottom: 0; }
|
||||
.hm-sw-property[data-selection-kind="all"] .hm-sw-property__counts { margin-top: -8px; }
|
||||
.hm-sw-property__group { flex: 0 0 auto; }
|
||||
|
||||
Reference in new issue
Block a user