feat(sw): integrated improvement 0.2.0 (popup content, header open, tool buttons)
SW package 0.2.0 integrated improvement (Task A, steps 1-8). All new props are
optional; existing SW Stories are pixel-identical to the previous build (28/28).
- Build reproducibility: dist text normalized to LF, dist/build-info.json
(commit, dirty, tool versions, no timestamp), packages/sw/.gitattributes
(eol=lf). LF checkouts give identical dist and tarball.
- SWHeader: documentOpenPlacement ("menu" default | "header": Open right of
the logo in the existing document-button look, reusing onDocumentOpen and
documentOpenLabel, no duplicate Open in the dropdown), leading slot,
hiddenControls sub-items documentNew / documentOpen / layerFreeze /
layerLock. Open moves into More on measured overflow (with hysteresis).
- showNew / showOpen (SWHeaderDocumentTitle), showFreeze / showLock (layer
menu, field, property window list).
- SWToolButton (text / pill / document) and SWToolGroup (radio selection),
reusing the existing toggle, pill and file-name looks.
- SWPopup / SWPopupSection / SWPopupRow on the shared property window frame;
SWHeaderPropertyPanel gains children, title, autoFocus and optional
selection / properties / groups. Escape stack for several popups.
- Field dropdowns inside a popup use the shared fixed overlay
(useSWFixedDropdownPosition), so the scrolling body no longer clips them.
- AI guide, examples E/F, README, Storybook (SW/Header/Options, SW/Tool,
SW/Popup) and verification record docs/sw/sw-integrated-improvement-2026-10-19.md.
- Regression scripts rescoped for the intended changes (unused-removal 81/81,
overview 52/54 with the two pre-existing historical assertions).
Known limitation (unresolved): tools / leading content (incl. SWToolGroup)
does not move into More. With a wide tool bar the configured fields shrink
instead; in Example F the document name and layer field reach 0px at 390px.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5faa1f1ffe
commit
55179b4577
138 files changed
+17194
-162
No files matched your search
@@ -377,7 +377,7 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: calc(var(--hm-sw-header-document-menu-width) + 2 * var(--hm-sw-header-document-menu-border-width));
|
||||
max-width: calc(100cqw - 71px);
|
||||
max-width: calc(100cqw - 71px - var(--hm-sw-header-leading-width, 0px));
|
||||
border: var(--hm-sw-header-document-menu-border-width) solid var(--hm-sw-header-document-menu-border-color);
|
||||
border-radius: 0 0 4px 4px;
|
||||
overflow: hidden;
|
||||
@@ -475,6 +475,8 @@
|
||||
border-top: 1px solid var(--hm-sw-header-document-menu-divider-color);
|
||||
box-shadow: var(--hm-sw-header-document-menu-inset-shadow);
|
||||
}
|
||||
/* A single remaining action keeps its Figma side: Open stays right, + New stays left. */
|
||||
.hm-sw-header__document-footer > [data-action="open"]:only-child { margin-left: auto; }
|
||||
.hm-sw-header__document-action {
|
||||
height: 24px;
|
||||
padding: 5px 6px;
|
||||
@@ -1724,7 +1726,7 @@ div.hm-sw-header__menu-row { justify-content: space-between; gap: 8px; padding-l
|
||||
The file name always takes the remaining width (ellipsis). cqw = header width.
|
||||
Hiding targets the flex item of each field ([data-menu] / [data-tier] on the field button, or on
|
||||
the wrapper of a field with a dropdown), so a dropdown field hides like a plain one. */
|
||||
.hm-sw-header__document { flex: 0 0 clamp(190px, calc(100cqw - 1610px), 310px); min-width: 0; }
|
||||
.hm-sw-header__document { flex: 0 0 clamp(190px, calc(100cqw - 1610px - var(--hm-sw-header-leading-width, 0px)), 310px); min-width: 0; }
|
||||
.hm-sw-header__field--layer { flex-shrink: 1; }
|
||||
.hm-sw-header__field:not(.hm-sw-header__field--layer) { flex-shrink: 0; }
|
||||
|
||||
@@ -1732,12 +1734,12 @@ div.hm-sw-header__menu-row { justify-content: space-between; gap: 8px; padding-l
|
||||
.hm-sw-header__fields > [data-tier="aux"] { display: none; }
|
||||
.hm-sw-header__more { display: block; }
|
||||
.hm-sw-header__more-item[data-tier="aux"] { display: flex; }
|
||||
.hm-sw-header__document { flex-basis: clamp(120px, calc(100cqw - 1030px), 310px); }
|
||||
.hm-sw-header__document { flex-basis: clamp(120px, calc(100cqw - 1030px - var(--hm-sw-header-leading-width, 0px)), 310px); }
|
||||
}
|
||||
@container hm-sw-header (max-width: 1179.98px) {
|
||||
.hm-sw-header__mode { display: none; }
|
||||
.hm-sw-header__fields { padding-left: 4px; }
|
||||
.hm-sw-header__document { flex-basis: clamp(120px, calc(100cqw - 944px), 310px); }
|
||||
.hm-sw-header__document { flex-basis: clamp(120px, calc(100cqw - 944px - var(--hm-sw-header-leading-width, 0px)), 310px); }
|
||||
}
|
||||
@container hm-sw-header (max-width: 1079.98px) {
|
||||
.hm-sw-header__properties { display: none; }
|
||||
@@ -1752,19 +1754,19 @@ div.hm-sw-header__menu-row { justify-content: space-between; gap: 8px; padding-l
|
||||
.hm-sw-header__motion-tooltip { left: calc(100% + 1px); top: 11px; }
|
||||
.hm-sw-header__motion:hover > .hm-sw-header__motion-tooltip { animation: none; opacity: 1; }
|
||||
.hm-sw-header__window { flex-basis: 176px; width: 176px; }
|
||||
.hm-sw-header__document { flex-basis: clamp(120px, calc(100cqw - 725px), 310px); }
|
||||
.hm-sw-header__document { flex-basis: clamp(120px, calc(100cqw - 725px - var(--hm-sw-header-leading-width, 0px)), 310px); }
|
||||
}
|
||||
@container hm-sw-header (max-width: 899.98px) {
|
||||
.hm-sw-header__fields > [data-menu="color"] { display: none; }
|
||||
.hm-sw-header__more-item[data-tier="narrow"] { display: flex; }
|
||||
.hm-sw-header__document { flex-basis: clamp(96px, calc(100cqw - 529px), 310px); }
|
||||
.hm-sw-header__document { flex-basis: clamp(96px, calc(100cqw - 529px - var(--hm-sw-header-leading-width, 0px)), 310px); }
|
||||
}
|
||||
@container hm-sw-header (max-width: 639.98px) {
|
||||
.hm-sw-header__actions,
|
||||
.hm-sw-header__motion { display: none; }
|
||||
.hm-sw-header__window { flex-basis: 64px; width: 64px; }
|
||||
.hm-sw-header__more-item[data-tier="action"] { display: flex; }
|
||||
.hm-sw-header__document { flex-basis: clamp(96px, calc(100cqw - 417px), 310px); }
|
||||
.hm-sw-header__document { flex-basis: clamp(96px, calc(100cqw - 417px - var(--hm-sw-header-leading-width, 0px)), 310px); }
|
||||
.hm-sw-header__document-button { padding-right: 8px; }
|
||||
}
|
||||
@container hm-sw-header (max-width: 519.98px) {
|
||||
@@ -1840,3 +1842,37 @@ div.hm-sw-header__menu-row { justify-content: space-between; gap: 8px; padding-l
|
||||
@container hm-sw-header (max-width: 1079.98px) {
|
||||
.hm-sw-header__window[data-reduced]:not(:has(.hm-sw-header__window-buttons:not([data-partial]))) .hm-sw-header__motion-tooltip { left: auto; right: calc(100% + 1px); }
|
||||
}
|
||||
|
||||
/* SW Tool (SWToolButton / SWToolGroup, 2026-10-19): the existing toggle, pill and file-name looks reused as
|
||||
public buttons. Only placement rules live here; every color, size and state comes from the rules above. */
|
||||
.hm-sw-tool__group { margin-inline: 0; }
|
||||
.hm-sw-tool__item { display: contents; }
|
||||
.hm-sw-tool__group .hm-sw-header__toggle { padding-inline: 8px; }
|
||||
.hm-sw-tool__icon { position: absolute; inset: 20.1% 20% 19.62%; display: grid; place-items: center; pointer-events: none; }
|
||||
.hm-sw-tool__icon > :is(img, svg) { display: block; max-width: 100%; max-height: 100%; }
|
||||
.hm-sw-tool__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
|
||||
/* File-name look as a button (e.g. Open next to the logo): content width, never the file-name clamp. */
|
||||
.hm-sw-header__document[data-tool] { flex: 0 0 auto; }
|
||||
.hm-sw-header__document[data-tool] > .hm-sw-header__document-button { width: auto; }
|
||||
|
||||
/* Leading area right of the logo (SWHeader documentOpenPlacement="header" / leading, 2026-10-19). It is the
|
||||
flex item the logo overlaps (like the file name), so the first file-name-look button keeps the Figma junction.
|
||||
Its measured width is --hm-sw-header-leading-width, subtracted from the file-name clamp above. */
|
||||
.hm-sw-header__leading { position: relative; z-index: 1; display: flex; flex: 0 0 auto; gap: 2px; height: var(--hm-sw-header-bar-height); }
|
||||
/* The file name after an Open button no longer sits under the logo: 12px start padding (D-1), not 5px. */
|
||||
:is(.hm-sw-header__leading, .hm-sw-header__document[data-tool]) + .hm-sw-header__document > .hm-sw-header__document-button { padding-left: 12px; }
|
||||
/* While the header Open is shown, the default fields keep their width: a lack of room becomes a measured
|
||||
overflow that moves Open into More instead of narrowing the layer field. Custom leading content alone keeps
|
||||
the existing behavior (file name first, then the layer field below 520px). */
|
||||
.hm-sw-header[data-leading="open"] .hm-sw-header__fields:not([data-configured]) > :is(.hm-sw-header__layer, .hm-sw-header__field--layer, .hm-sw-header__control[data-control="layer"]) { flex-shrink: 0; }
|
||||
.hm-sw-header__more[data-forced] { display: block; }
|
||||
/* Tool groups reuse the 상세보기 / print-K surfaces but are host tools: the Header breakpoints that move those
|
||||
built-in parts into More never hide them (they have no More entry). */
|
||||
.hm-sw-header__properties.hm-sw-tool__group { display: flex; }
|
||||
.hm-sw-header__actions.hm-sw-tool__pill { display: flex; }
|
||||
/* Configured layouts too: while the header Open is shown, controls other than the file name keep their width,
|
||||
so a lack of room is a measured overflow that moves Open into More (the file name still gives way first). */
|
||||
.hm-sw-header[data-leading="open"] .hm-sw-header__fields[data-configured] > .hm-sw-header__control:not([data-control="document"]),
|
||||
.hm-sw-header[data-leading="open"] .hm-sw-header__fields[data-configured] > .hm-sw-header__control:not([data-control="document"]) > * { flex-shrink: 0; }
|
||||
/* ...and the file name gives way only down to the default design's smallest width (96px, see the clamps above). */
|
||||
.hm-sw-header[data-leading="open"] .hm-sw-header__fields[data-configured] > .hm-sw-header__control[data-control="document"] { min-width: 96px; }
|
||||
Reference in new issue
Block a user