feat(sw): implement property field interaction variants
- Property panel rows follow Figma 26:12388 ~ 26:12649: 28px fields with Default / Hover border / numeric editing On (#0F0D0A) / dropdown On (#211D13) - Layer, line style and color fields open the shared header dropdown contents (SWHeaderLayerRows, SWHeaderLineStyleColumns, SWHeaderColorPanelBody) - Additive API: property.picker, property.decimals, panel menus - Property Fields story and browser test (77 checks) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
724c51732b
commit
0029cef60c
23 files changed
+1907
-189
No files matched your search
@@ -75,6 +75,12 @@
|
||||
--hm-sw-property-label: #000;
|
||||
--hm-sw-property-table: #d2c8b4;
|
||||
--hm-sw-property-inner-border: #948871;
|
||||
/* Property fields (Figma 26:12170 ~ 26:12649): Hover border, editing On, dropdown On, unit colors. */
|
||||
--hm-sw-property-field-hover-border-color: rgba(33, 29, 19, 0.4);
|
||||
--hm-sw-property-field-editing-background: #0f0d0a;
|
||||
--hm-sw-property-field-open-background: #211d13;
|
||||
--hm-sw-property-field-editing-unit-color: #fff;
|
||||
--hm-sw-property-field-open-unit-color: #d4cbbd;
|
||||
/* Gauge (user-supplied Figma SVGs, 2026-10-19). Fill = Rectangle 6926: 6px pill, 1px black stroke,
|
||||
vertical #8E0000 / #FF4242 37% / #E40000 76% / #1E0000 inside the stroke; its right end sits under
|
||||
the thumb. Unfilled track = beige measured row by row from the user's reference image.
|
||||
@@ -1520,8 +1526,10 @@ div.hm-sw-header__menu-row { justify-content: space-between; gap: 8px; padding-l
|
||||
.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__unit { flex: 0 0 auto; font-size: 12px; white-space: nowrap; }
|
||||
.hm-sw-property__swatch { display: block; flex: 0 0 70px; height: 16px; padding: 1px; border: 1px solid #000; border-radius: 2px; }
|
||||
.hm-sw-property__swatch > i { display: block; height: 12px; border: 1px solid #fff; }
|
||||
/* 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; }
|
||||
/* --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
|
||||
@@ -1582,6 +1590,107 @@ div.hm-sw-header__menu-row { justify-content: space-between; gap: 8px; padding-l
|
||||
.hm-sw-property__row[data-disabled="true"] { opacity: .4; }
|
||||
.hm-sw-property button:focus-visible, .hm-sw-property input:focus-visible, .hm-sw-property select:focus-visible { outline: 2px solid var(--hm-sw-property-border); outline-offset: -2px; }
|
||||
|
||||
/* Property fields (2026-10-19, Figma 26:12170 ~ 26:12649). Common rows only; the circle / position groups keep
|
||||
their layout. Box: 28px, radius 2, a transparent 1px border so Hover / On never move the value (8px inset as
|
||||
in Default). Default: value only. Hover: rgba(33,29,19,.4) border, values / units / previews unchanged.
|
||||
On (editing, numbers 26:12323 / 26:12599 / 26:12656): #0F0D0A, black text outline, unit #FFF, red caret.
|
||||
On (dropdown 26:12265 / 26:12291 / 26:12404 / 26:12184): #211D13, outlined value, unit #D4CBBD.
|
||||
Text and computed values (26:12583 / 26:12574) have no Figma On: only Default / Hover. */
|
||||
.hm-sw-property__group--rows .hm-sw-property__value[data-field] {
|
||||
position: relative;
|
||||
height: 28px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 2px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.hm-sw-property__group--rows .hm-sw-property__value[data-field="box"] { padding: 0 7px; }
|
||||
.hm-sw-property__group--rows .hm-sw-property__value[data-field="picker"] { padding: 0; }
|
||||
.hm-sw-property__group--rows .hm-sw-property__row:not([data-disabled]) > .hm-sw-property__value[data-field]:is(:hover, [data-open="true"], :not([data-readonly]):focus-within) {
|
||||
border-color: var(--hm-sw-property-field-hover-border-color);
|
||||
}
|
||||
.hm-sw-property__group--rows .hm-sw-property__value[data-field] .hm-sw-header__input,
|
||||
.hm-sw-property__group--rows .hm-sw-property__value[data-field] .hm-sw-header__input:is(:hover, :focus) {
|
||||
flex: 1 1 auto;
|
||||
align-self: stretch;
|
||||
width: auto;
|
||||
min-width: 0;
|
||||
height: auto;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.02em;
|
||||
text-shadow: none;
|
||||
}
|
||||
/* The box shows the editing state; read-only values keep the keyboard focus ring. */
|
||||
.hm-sw-property__group--rows .hm-sw-property__value[data-field] .hm-sw-header__input:not(:read-only):focus-visible { outline: none; }
|
||||
.hm-sw-property__group--rows .hm-sw-property__value[data-on="edit"]:focus-within { background: var(--hm-sw-property-field-editing-background); }
|
||||
.hm-sw-property__group--rows .hm-sw-property__value[data-on="edit"]:focus-within > .hm-sw-header__input { text-shadow: var(--hm-sw-header-text-outline); }
|
||||
.hm-sw-property__group--rows .hm-sw-property__value[data-on="edit"]:focus-within > .hm-sw-property__unit { color: var(--hm-sw-property-field-editing-unit-color); }
|
||||
|
||||
/* 41px hug field (26:12649: 선가중치 / 투명도 value): pl 6, pr 4, the input itself is the box. */
|
||||
.hm-sw-property__group--rows .hm-sw-property__value > .hm-sw-header__input.hm-sw-property__compact,
|
||||
.hm-sw-property__group--rows .hm-sw-property__value > .hm-sw-header__input.hm-sw-property__compact:is(:hover, :focus) {
|
||||
flex: 0 0 auto;
|
||||
width: calc(var(--hm-sw-input-chars, 1) * (1ch + 0.02em) + 10px);
|
||||
height: 28px;
|
||||
padding: 0 3px 0 5px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 2px;
|
||||
background: transparent;
|
||||
}
|
||||
@supports (field-sizing: content) {
|
||||
.hm-sw-property__group--rows .hm-sw-property__value > .hm-sw-header__input.hm-sw-property__compact { width: auto; min-width: calc(1ch + 10px); }
|
||||
}
|
||||
.hm-sw-property__group--rows .hm-sw-property__row:not([data-disabled]) .hm-sw-header__input.hm-sw-property__compact:is(:hover, :focus:not(:read-only)) { border-color: var(--hm-sw-property-field-hover-border-color); }
|
||||
.hm-sw-property__group--rows .hm-sw-property__value > .hm-sw-header__input.hm-sw-property__compact:focus:not(:read-only) {
|
||||
outline: none;
|
||||
background: var(--hm-sw-property-field-editing-background);
|
||||
text-shadow: var(--hm-sw-header-text-outline);
|
||||
}
|
||||
|
||||
/* Dropdown fields: layer (pl/pr 8), line style (pl 8, pr 6: value + (ByL) + pattern), color (RGB | swatch). */
|
||||
.hm-sw-property__trigger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 4px;
|
||||
flex: 1 1 auto;
|
||||
align-self: stretch;
|
||||
min-width: 0;
|
||||
padding: 0 7px;
|
||||
color: var(--hm-sw-header-input-color);
|
||||
text-align: left;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
.hm-sw-property__value[data-picker="lineStyle"] > .hm-sw-property__trigger { padding-right: 5px; }
|
||||
.hm-sw-property__value[data-readonly] > .hm-sw-property__trigger,
|
||||
.hm-sw-property__trigger:disabled { cursor: default; opacity: 1; }
|
||||
.hm-sw-property__trigger-text { display: flex; align-items: center; gap: 4px; min-width: 0; }
|
||||
.hm-sw-property__text { min-width: 0; overflow: clip; overflow-clip-margin: var(--hm-sw-header-text-outline-room); white-space: nowrap; text-overflow: ellipsis; font-weight: 500; }
|
||||
.hm-sw-property__trigger .hm-sw-property__unit { color: var(--hm-sw-property-label); }
|
||||
/* Figma 68px (Dotum). Noto Sans KR needs more room for "Continuous (ByL)": the preview gives way first (Figma On draws it at 50px), then the name ellipsizes. */
|
||||
.hm-sw-property__trigger > .hm-sw-header__line-preview { flex: 0 1 68px; width: 68px; min-width: 40px; }
|
||||
.hm-sw-property__value[data-picker="lineStyle"] .hm-sw-property__trigger-text { flex-shrink: 0; max-width: calc(100% - 44px); }
|
||||
.hm-sw-property__value[data-field="picker"][data-open="true"]:not([data-picker="color"]),
|
||||
.hm-sw-property__value[data-picker="color"][data-open="true"] > .hm-sw-property__color-value { background: var(--hm-sw-property-field-open-background); }
|
||||
.hm-sw-property__group--rows .hm-sw-property__value[data-field][data-open="true"] :is(.hm-sw-property__text, .hm-sw-header__input) { text-shadow: var(--hm-sw-header-text-outline); }
|
||||
.hm-sw-property__value[data-open="true"] .hm-sw-property__trigger .hm-sw-property__unit { color: var(--hm-sw-property-field-open-unit-color); }
|
||||
.hm-sw-property__color-value { display: flex; align-items: center; flex: 1 1 auto; align-self: stretch; min-width: 0; padding: 0 7px; border-right: 1px solid transparent; }
|
||||
.hm-sw-property__value[data-field] > .hm-sw-property__swatch-area { align-self: stretch; padding: 0 5px; }
|
||||
.hm-sw-property__value[data-field="box"] > .hm-sw-property__swatch-area { padding-right: 0; }
|
||||
.hm-sw-property__value[data-picker="color"]:not([data-readonly]) > .hm-sw-property__swatch-area { cursor: pointer; }
|
||||
.hm-sw-property__group--rows .hm-sw-property__row:not([data-disabled]) > .hm-sw-property__value[data-picker="color"]:is(:hover, [data-open="true"]) > .hm-sw-property__color-value {
|
||||
border-right-color: var(--hm-sw-property-field-hover-border-color);
|
||||
}
|
||||
/* The shared header dropdown contents in a fixed overlay (escapes the scrolling body). No yellow ring:
|
||||
the property Figma dropdowns have the black stroke and the brown surface only. */
|
||||
.hm-sw-property__drop { position: fixed; z-index: 50; top: 0; left: 0; color: var(--hm-sw-header-text-color); text-align: left; }
|
||||
.hm-sw-property__drop[data-picker="layer"] { width: var(--hm-sw-header-layer-menu-width); }
|
||||
.hm-sw-property__drop.hm-sw-header__menu-panel { position: fixed; max-width: none; }
|
||||
.hm-sw-property__drop.hm-sw-header__menu-panel::before { display: none; }
|
||||
|
||||
/* K guide 26:11698 / 26:11669: original image, fixed mask viewport and continuous pan/zoom. */
|
||||
.hm-sw-k-guide { position: relative; flex: 0 0 40px; height: 38px; }
|
||||
.hm-sw-k-guide__panel { z-index: 45; height: 149px; min-height: 149px; overflow: hidden; border: 1px solid var(--hm-sw-property-border); border-radius: 2px; background: #0e3c2e; animation: hm-sw-k-guide-enter 511ms ease-out; }
|
||||
|
||||
Reference in new issue
Block a user