feat(sw): popup controls, SWSelect / SWSlider, footer and viewer design fixes

Components (new public exports, existing APIs unchanged)
- SWPopupPropertyRow: the property window row (layer / color / line style
  pickers, Figma 26:12250 / 26:12170) for SWPopup content. The SWHeader field
  dropdowns stay header-only; Popup B and 도면 설정 now use the popup pickers.
- SWSelect: native panel select (28px, 1px #948871, radius 4, #F1ECE1, 12px),
  used by Popup 도면 설정 단위 and Viewer 축척 지정 단위 (replaces the HM UI
  Select there and the story-only .sw-viewer-story-select CSS).
- SWSlider: appearance "panel" (default, the gauge the popup used) or
  "property" (the property window gauge), same value / events. Shares the
  property gauge CSS; SWViewerSlider renders SWSlider panel with viewer tokens.

Footer
- --hm-sw-footer-gra-border-orange (Figma gra-border-orange; the aux selected
  border token now references it): Model selected / hover, Layout hover and
  Layout + hover surfaces; 보조기능 / 명령어 전체보기 hover lights both lines
  and an orange ring; category + hover in #FF5C00 (menu-add-hover.svg).
- Model / Layout text stays the Default text (#161410, 12px, 400, no outline)
  on hover and on the orange surface: only the surface changes.
- bg_vacant covers the slot row only: the open pocket of a category tab no
  longer splits where it crosses the last command (e.g. 수정 with one command).

Viewer
- Panel title art keeps 308px (max-width: none against host img resets), so
  panels under 312px (250 x auto, 300px) paint the title from the left edge.

Storybook
- SW/Footer: 기본 Footer (sw-footer--default) and States (sw-footer--states)
  removed; full-footer keeps the live composition only, responsive keeps the
  widths (reference / Figma image sections removed, image files kept); the aux
  Figma comparison moved to the verification Story figma-variants.
- SW/Popup: unit SWSelect, SWSlider A / B section, popup pickers, Popup B state.
This commit is contained in:
shkim4 committed 2026-10-20 15:20:06 +09:00
1 parent bbb0e71c91
commit 126a35d60d
15 files changed
+349 -209

No files matched your search

+46 -10
View File
@@ -100,6 +100,17 @@
--hm-sw-property-range-fill-edge: #000;
--hm-sw-property-range-track: linear-gradient(#aea28b 0 1px, #c3b9a4 1px 2px, #c7bda9 2px 4px, #b7ac96 4px 5px, #ac9e84 5px);
--hm-sw-property-range-highlight: #eadec8;
/* SWSlider appearance "panel" (2026-10-20): the gauge the SW popup used so far (HM UI Slider: 6px #E0DACE
track, #266651 range, 18px white thumb with a 2px #266651 ring), the same shape as SWViewerSlider. Existing
values only (#E0DACE = popup scrollbar track, #266651 = viewer panel accent). Appearance "property" uses the
--hm-sw-property-range-* tokens above. */
--hm-sw-slider-panel-track: #e0dace;
--hm-sw-slider-panel-range: #266651;
--hm-sw-slider-panel-thumb: #fff;
/* SWSelect (2026-10-20): the panel field values of the viewer 축척 지정 select (property inner border / content). */
--hm-sw-select-border-color: var(--hm-sw-property-inner-border);
--hm-sw-select-background: var(--hm-sw-property-content);
--hm-sw-select-text: var(--hm-sw-property-label);
/* User-confirmed: document (file name) surface */
--hm-sw-header-document-background: linear-gradient(180deg, #081813 0%, #09271e 8.69%, #0b3227 25.43%, #0e3d2f 51.25%, #0b3227 80.03%, #0a2b21 89.76%, #081813 100%);
@@ -1541,20 +1552,25 @@ div.hm-sw-header__menu-row { justify-content: space-between; gap: 8px; padding-l
.hm-sw-property__value { display: flex; align-items: center; gap: 4px; flex: 1; min-width: 0; }
.hm-sw-property__value > .hm-sw-header__input { width: auto; max-width: 100%; min-width: 0; flex: 1; text-shadow: none; letter-spacing: .02em; font-weight: 500; }
.hm-sw-property__value > .hm-sw-header__input:focus { color: var(--hm-sw-header-input-color); }
.hm-sw-property__value > select { flex: 1; min-width: 0; width: 0; height: 28px; padding: 0; appearance: none; border: 1px solid transparent; border-radius: 2px; background: transparent; color: var(--hm-sw-header-input-color); font: inherit; }
.hm-sw-property__value > select:disabled { opacity: 1; appearance: none; color: var(--hm-sw-header-input-color); }
.hm-sw-property__value > select:focus { background: var(--hm-sw-property-content); border-color: var(--hm-sw-property-inner-border); }
.hm-sw-property__value > select:not(.hm-sw-select) { flex: 1; min-width: 0; width: 0; height: 28px; padding: 0; appearance: none; border: 1px solid transparent; border-radius: 2px; background: transparent; color: var(--hm-sw-header-input-color); font: inherit; }
.hm-sw-property__value > select:not(.hm-sw-select):disabled { opacity: 1; appearance: none; color: var(--hm-sw-header-input-color); }
.hm-sw-property__value > select:not(.hm-sw-select):focus { background: var(--hm-sw-property-content); border-color: var(--hm-sw-property-inner-border); }
/* SWSelect: native select, panel field look; focus = the SW popup focus ring. */
.hm-sw-select { flex: 0 0 auto; height: 28px; padding: 0 8px; border: 1px solid var(--hm-sw-select-border-color); border-radius: 4px; background: var(--hm-sw-select-background); color: var(--hm-sw-select-text); font: inherit; font-size: 12px; }
.hm-sw-select:disabled { opacity: 0.4; cursor: default; }
.hm-sw-property__unit { flex: 0 0 auto; font-size: 12px; white-space: nowrap; }
/* Color preview (26:12175): 70 x 16 black tile (1px padding, radius 2), 68 x 14 swatch with a white 1px border. */
.hm-sw-property__swatch-area { display: flex; align-items: center; flex: 0 0 auto; }
.hm-sw-property__swatch { display: block; flex: 0 0 70px; width: 70px; height: 16px; padding: 1px; border-radius: 2px; background: #000; }
.hm-sw-property__swatch > i { display: block; height: 14px; border: 1px solid #fff; border-radius: 1px; }
.hm-sw-property__value > input[type="range"] { appearance: none; flex: 0 0 86px; width: 86px; height: 16px; margin: 0; background: transparent; cursor: pointer; }
/* Property window gauge, also SWSlider appearance="property" (2026-10-20, same rules; the 86px width is the property row only). */
.hm-sw-property__value > input[type="range"]:not(.hm-sw-slider) { flex: 0 0 86px; width: 86px; }
:is(.hm-sw-property__value > input[type="range"]:not(.hm-sw-slider), .hm-sw-slider[data-appearance="property"]) { appearance: none; height: 16px; margin: 0; background: transparent; cursor: pointer; }
/* --hm-sw-range-fill (0-1) is set from the value; the red ends under the thumb centre (14px thumb).
The 3px radius rounds the fill's left cap; the first layer is its left stroke. Track and thumb are
shared values, painted once per engine: WebKit/Blink track + thumb, Gecko track + thumb (Gecko's
::-moz-range-progress is kept empty so the fill is never painted twice). */
.hm-sw-property__value > input[type="range"] {
:is(.hm-sw-property__value > input[type="range"]:not(.hm-sw-slider), .hm-sw-slider[data-appearance="property"]) {
--hm-sw-range-fill-width: calc(7px + (100% - 14px) * var(--hm-sw-range-fill, 0));
--hm-sw-range-track-paint:
linear-gradient(90deg, var(--hm-sw-property-range-fill-edge) 0 1px, transparent 1px) 0 0 / var(--hm-sw-range-fill-width) 100% no-repeat,
@@ -1563,11 +1579,31 @@ div.hm-sw-header__menu-row { justify-content: space-between; gap: 8px; padding-l
--hm-sw-range-thumb-paint: url("../assets/property-range-thumb.svg") center / 14px 14px no-repeat;
--hm-sw-range-thumb-shadow: 0 0 3px #1c1a16, 0 2px 2px rgba(28, 26, 22, .4);
}
.hm-sw-property__value > input[type="range"]::-webkit-slider-runnable-track { height: 6px; border-radius: 3px; background: var(--hm-sw-range-track-paint); box-shadow: 0 1px 0 var(--hm-sw-property-range-highlight); }
.hm-sw-property__value > input[type="range"]::-webkit-slider-thumb { appearance: none; width: 14px; height: 14px; margin-top: -4px; border: 0; border-radius: 50%; background: var(--hm-sw-range-thumb-paint); box-shadow: var(--hm-sw-range-thumb-shadow); }
.hm-sw-property__value > input[type="range"]::-moz-range-track { box-sizing: border-box; height: 6px; border: 0; border-radius: 3px; background: var(--hm-sw-range-track-paint); box-shadow: 0 1px 0 var(--hm-sw-property-range-highlight); }
.hm-sw-property__value > input[type="range"]::-moz-range-progress { height: 0; background: transparent; }
.hm-sw-property__value > input[type="range"]::-moz-range-thumb { box-sizing: border-box; width: 14px; height: 14px; border: 0; border-radius: 50%; background: var(--hm-sw-range-thumb-paint); box-shadow: var(--hm-sw-range-thumb-shadow); }
:is(.hm-sw-property__value > input[type="range"]:not(.hm-sw-slider), .hm-sw-slider[data-appearance="property"])::-webkit-slider-runnable-track { height: 6px; border-radius: 3px; background: var(--hm-sw-range-track-paint); box-shadow: 0 1px 0 var(--hm-sw-property-range-highlight); }
:is(.hm-sw-property__value > input[type="range"]:not(.hm-sw-slider), .hm-sw-slider[data-appearance="property"])::-webkit-slider-thumb { appearance: none; width: 14px; height: 14px; margin-top: -4px; border: 0; border-radius: 50%; background: var(--hm-sw-range-thumb-paint); box-shadow: var(--hm-sw-range-thumb-shadow); }
:is(.hm-sw-property__value > input[type="range"]:not(.hm-sw-slider), .hm-sw-slider[data-appearance="property"])::-moz-range-track { box-sizing: border-box; height: 6px; border: 0; border-radius: 3px; background: var(--hm-sw-range-track-paint); box-shadow: 0 1px 0 var(--hm-sw-property-range-highlight); }
:is(.hm-sw-property__value > input[type="range"]:not(.hm-sw-slider), .hm-sw-slider[data-appearance="property"])::-moz-range-progress { height: 0; background: transparent; }
:is(.hm-sw-property__value > input[type="range"]:not(.hm-sw-slider), .hm-sw-slider[data-appearance="property"])::-moz-range-thumb { box-sizing: border-box; width: 14px; height: 14px; border: 0; border-radius: 50%; background: var(--hm-sw-range-thumb-paint); box-shadow: var(--hm-sw-range-thumb-shadow); }
/* SWSlider (2026-10-20): one native range, two looks. Fills the row by default (the host may set a width).
appearance="panel" is the gauge the SW popup used (also SWViewerSlider): the range is painted up to
--hm-sw-range-fill of the track. */
.hm-sw-slider { flex: 1 1 auto; width: 100%; min-width: 0; }
.hm-sw-slider:disabled { opacity: 0.4; cursor: default; }
.hm-sw-slider[data-appearance="panel"] {
--hm-sw-slider-percent: calc(var(--hm-sw-range-fill, 0) * 100%);
height: 18px;
margin: 0;
background: transparent;
appearance: none;
cursor: pointer;
}
.hm-sw-slider[data-appearance="panel"]:disabled { cursor: default; }
.hm-sw-slider[data-appearance="panel"]::-webkit-slider-runnable-track { height: 6px; border-radius: 9999px; background: linear-gradient(90deg, var(--hm-sw-slider-panel-range) var(--hm-sw-slider-percent), var(--hm-sw-slider-panel-track) var(--hm-sw-slider-percent)); }
.hm-sw-slider[data-appearance="panel"]::-moz-range-track { height: 6px; border-radius: 9999px; background: var(--hm-sw-slider-panel-track); }
.hm-sw-slider[data-appearance="panel"]::-moz-range-progress { height: 6px; border-radius: 9999px; background: var(--hm-sw-slider-panel-range); }
.hm-sw-slider[data-appearance="panel"]::-webkit-slider-thumb { width: 18px; height: 18px; margin-top: -6px; border: 2px solid var(--hm-sw-slider-panel-range); border-radius: 9999px; background: var(--hm-sw-slider-panel-thumb); appearance: none; }
.hm-sw-slider[data-appearance="panel"]::-moz-range-thumb { box-sizing: border-box; width: 18px; height: 18px; border: 2px solid var(--hm-sw-slider-panel-range); border-radius: 9999px; background: var(--hm-sw-slider-panel-thumb); }
.hm-sw-slider[data-appearance="panel"]:focus-visible { outline: 2px solid var(--hm-sw-slider-panel-range); outline-offset: 2px; }
.hm-sw-property__value > .hm-sw-header__line-preview { flex-basis: 68px; width: 68px; }
.hm-sw-property__expand { display: block; width: 100%; height: 12px; overflow: hidden; }
.hm-sw-property__expand > img { display: block; width: 296px; height: 12px; margin-left: calc((100% - 296px) / 2); }