fix(sw): 2026-10-21 SW design review and responsive header without More from 760px
User-approved design review (2026-10-21): - SW Header: from 760px up nothing moves into More; the five menus stay with their titles (titles and values ellipsize), file name shrinks to 96px. Open next to the logo no longer blocks field shrinking above 760px (760/768 overflow fixed, also for configured `controls` headers). Dropdown yellow ring inside the button, black seam. - Property Bar values as read-only red text; property popup "=" labels, read-only black values, per-entry hover with pointer. - Home Menu recent files (3 rows, path + name caption, empty preview), Footer + slot guide off by default, Viewer file list without icons, Storybook widths 1920-760. - Tests: old More expectations (integrated-improvement, keyboard-dismiss, footer-popup-viewer-refinement, storybook-cleanup-stage1) moved to the new rule; functional checks kept.
This commit is contained in:
1 parent
a25d2b31c5
commit
2fc1b3e108
37 files changed
+447
-211
No files matched your search
@@ -41,6 +41,8 @@ const defaultControls: SWHeaderControlConfig[] = (["document", "drawingMode", ..
|
||||
const frameControls: readonly SWHeaderFrameControlId[] = ["home", "windowMove", "minimize", "close"]
|
||||
const subControls: readonly SWHeaderSubControlId[] = ["documentNew", "documentOpen", "layerFreeze", "layerLock"]
|
||||
const isMenu = (id: string): id is SWHeaderMenuId => id in menuSlot
|
||||
/** Header width from which nothing moves into More (2026-10-21): the header compresses instead. Below it, as before. */
|
||||
const MORE_BELOW = 760
|
||||
|
||||
/**
|
||||
* Order in which visible parts move into More when the measured object area has no room left (on top of the
|
||||
@@ -318,7 +320,10 @@ export const SWHeader = forwardRef<HTMLElement, SWHeaderProps>(function SWHeader
|
||||
const menuIds = configuration.map(item => item.id).filter((id): id is SWHeaderMenuId => id in menuSlot)
|
||||
const baseMenu = menuIds.includes("layer") ? "layer" : menuIds[0]
|
||||
const validPromoted = promoted && enabled(promoted) ? promoted : null
|
||||
const breakpointOverflowAt = (id: SWHeaderControlId, width: number) => id === "color" ? width < 900 : ["lineStyle", "textStyle", "dimensionStyle"].includes(id) ? width < 1800 : ["propertyBar", "propertyPanel", "details"].includes(id) ? width < 1080 : ["print", "popupGuide"].includes(id) ? width < 640 : id === "drawingMode" ? width < 1180 : false
|
||||
// 2026-10-21 (user decision): no responsive More from 760px up. Nothing moves out of the header there; narrower headers
|
||||
// hide the field titles, then shrink the file name, then the field values (ellipsis, sw.css "Responsive"). Below 760px
|
||||
// (phones, e.g. 390) the former breakpoints and More are unchanged.
|
||||
const breakpointOverflowAt = (id: SWHeaderControlId, width: number) => width < MORE_BELOW && (id === "color" ? width < 900 : ["lineStyle", "textStyle", "dimensionStyle"].includes(id) ? width < 1800 : ["propertyBar", "propertyPanel", "details"].includes(id) ? width < 1080 : ["print", "popupGuide"].includes(id) ? width < 640 : id === "drawingMode" ? width < 1180 : false)
|
||||
const breakpointOverflow = (id: SWHeaderControlId) => breakpointOverflowAt(id, headerWidth)
|
||||
// Measured More: the parts that can move (the default layout moves the property block as one part; print / K sit in
|
||||
// the window area there and keep the breakpoint). Keys of the moved parts are kept in move order.
|
||||
@@ -373,6 +378,13 @@ export const SWHeader = forwardRef<HTMLElement, SWHeaderProps>(function SWHeader
|
||||
collapseRef.current = null
|
||||
if (openCollapsed) return setOpenCollapsed(false)
|
||||
}
|
||||
// No responsive More from 760px up (2026-10-21): the header compresses instead. Below it the measured More runs as
|
||||
// before; parts it moved leave silently once the header is that wide again.
|
||||
if (headerWidth >= MORE_BELOW) {
|
||||
if (squeezed.length) { squeezeRef.current.clear(); return setSqueezed([]) }
|
||||
if (openCollapsed) { collapseRef.current = null; return setOpenCollapsed(false) }
|
||||
return
|
||||
}
|
||||
if (widthRef.current.current !== headerWidth) widthRef.current = { previous: widthRef.current.current, current: headerWidth }
|
||||
const { previous } = widthRef.current
|
||||
if (releasedRef.current.width !== headerWidth) releasedRef.current = { width: headerWidth, keys: new Set() }
|
||||
|
||||
Reference in new issue
Block a user