Initial commit: HMDesignSystem baseline
This commit is contained in:
commit
b6a0a61103
486 files changed
+68432
No files matched your search
@@ -0,0 +1,203 @@
|
||||
/* Select mapping: the trigger and its connected list. Label and Helper/Error text are consumer composition.
|
||||
States use the Radix attributes (data-state, data-placeholder, data-highlighted, data-side) and :disabled; size uses data-size. */
|
||||
:root, [data-hm-theme] {
|
||||
/* ui_viz: docs/components/select.md §1.1 D-004, §8 — Confirmed. Control height is the inner height: the 1px border is added
|
||||
around it (outer 34 / 44). Not aliased to Input or Button. */
|
||||
--hm-select-control-height-md: 32px;
|
||||
--hm-select-control-height-lg: 42px;
|
||||
--hm-select-border-width: 1px;
|
||||
/* ui_viz: docs/components/select.md §8, §17 — BASELINE_VALUE (current applied contract) */
|
||||
--hm-select-padding-x: 12px;
|
||||
--hm-select-gap: 12px;
|
||||
/* ui_viz select.md §8: Option min-height 42 for both sizes (no medium value defined). Kept as one token per size so a
|
||||
later Medium decision changes only this line. */
|
||||
--hm-select-option-height-md: 42px;
|
||||
--hm-select-option-height-lg: 42px;
|
||||
--hm-select-radius: var(--hm-radius-input);
|
||||
|
||||
/* ui_viz: docs/components/select.md §9 — large body-md 16/24/400, medium trigger body-sm 14/20/400, option body-md in both sizes */
|
||||
--hm-select-font-size-md: 14px;
|
||||
--hm-select-line-height-md: 20px;
|
||||
--hm-select-font-size-lg: 16px;
|
||||
--hm-select-line-height-lg: 24px;
|
||||
/* Option typography follows the Select size (Trigger and list share one size). ui_viz left the Medium Option Role open
|
||||
(TBD, medium Trigger body-sm vs Option body-md); the Medium Option takes the Medium Trigger value 14/20/400. */
|
||||
--hm-select-option-font-size-md: var(--hm-select-font-size-md);
|
||||
--hm-select-option-line-height-md: var(--hm-select-line-height-md);
|
||||
--hm-select-option-font-size-lg: var(--hm-select-font-size-lg);
|
||||
--hm-select-option-line-height-lg: var(--hm-select-line-height-lg);
|
||||
--hm-select-font-weight: 400;
|
||||
|
||||
/* ui_viz: docs/components/select.md §10, §1.3 — Confirmed (D-005, M06) */
|
||||
--hm-select-background: var(--hm-sem-bg-surface);
|
||||
--hm-select-text: var(--hm-sem-fg-primary);
|
||||
--hm-select-placeholder: var(--hm-sem-fg-placeholder);
|
||||
--hm-select-border-color: var(--hm-sem-stroke-input-default);
|
||||
--hm-select-focus-border-color: var(--hm-sem-stroke-input-focus);
|
||||
--hm-select-seam-color: var(--hm-sem-stroke-input-default);
|
||||
/* Open list face measured from the target Open screen: #e1f1ec on the white list = 45% of --accent (#bddfd4).
|
||||
Same mix the Toggle/Calendar hover faces use. The list shadow is the target's soft, downward-offset one (not the floating-surface shadow). */
|
||||
--hm-select-option-state-background: var(--hm-sem-surface-highlight);
|
||||
--hm-select-option-state-text: var(--accent-foreground);
|
||||
--hm-select-content-shadow: 0 2px 24px color-mix(in srgb, var(--hm-sem-palette-black) 12%, transparent);
|
||||
|
||||
/* ui_viz: docs/components/select.md §1.2 — user-confirmed Disabled: opacity .6, same white face and #DEDBD2 border */
|
||||
--hm-select-disabled-opacity: 0.6;
|
||||
/* ui_viz: docs/components/select.md §7 — indicator glyph stroke (user-provided Source) */
|
||||
--hm-select-indicator-color: var(--hm-sem-palette-indicator);
|
||||
}
|
||||
|
||||
/* Trigger. Large is the default when size is omitted. */
|
||||
[data-slot="select-trigger"] {
|
||||
--hm-select-control-height: var(--hm-select-control-height-lg);
|
||||
--hm-select-font-size: var(--hm-select-font-size-lg);
|
||||
--hm-select-line-height: var(--hm-select-line-height-lg);
|
||||
box-sizing: border-box;
|
||||
min-width: 0;
|
||||
height: auto;
|
||||
min-height: calc(var(--hm-select-control-height) + 2 * var(--hm-select-border-width));
|
||||
gap: var(--hm-select-gap);
|
||||
padding: 0 var(--hm-select-padding-x);
|
||||
border: var(--hm-select-border-width) solid var(--hm-select-border-color);
|
||||
border-radius: var(--hm-select-radius);
|
||||
background: var(--hm-select-background);
|
||||
color: var(--hm-select-text);
|
||||
font-size: var(--hm-select-font-size);
|
||||
line-height: var(--hm-select-line-height);
|
||||
font-weight: var(--hm-select-font-weight);
|
||||
}
|
||||
[data-slot="select-trigger"] > [data-slot="select-value"] {
|
||||
min-width: 0;
|
||||
flex: 1 1 auto;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
[data-slot="select-trigger"][data-size="medium"] {
|
||||
--hm-select-control-height: var(--hm-select-control-height-md);
|
||||
--hm-select-font-size: var(--hm-select-font-size-md);
|
||||
--hm-select-line-height: var(--hm-select-line-height-md);
|
||||
}
|
||||
[data-slot="select-trigger"][data-placeholder] {
|
||||
color: var(--hm-select-placeholder);
|
||||
}
|
||||
[data-slot="select-icon"] {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
color: var(--hm-select-indicator-color);
|
||||
}
|
||||
|
||||
/* Focus and Open retain the focus-colored outer outline. The connected edge follows Content's actual side. */
|
||||
[data-slot="select-trigger"]:focus {
|
||||
border-color: var(--hm-select-focus-border-color);
|
||||
}
|
||||
[data-slot="select-trigger"][data-state="open"] {
|
||||
border-color: var(--hm-select-focus-border-color);
|
||||
}
|
||||
|
||||
/* Direction is mirrored from the actual Radix Content through its ARIA relationship. */
|
||||
[data-slot="select-trigger"][data-state="open"][data-side="bottom"] {
|
||||
border-radius: var(--hm-select-radius) var(--hm-select-radius) 0 0;
|
||||
border-bottom-color: var(--hm-select-seam-color);
|
||||
}
|
||||
[data-slot="select-trigger"][data-state="open"][data-side="top"] {
|
||||
border-radius: 0 0 var(--hm-select-radius) var(--hm-select-radius);
|
||||
border-top-color: var(--hm-select-seam-color);
|
||||
}
|
||||
|
||||
/* Disabled keeps the Default paint and dims the whole control. */
|
||||
[data-slot="select-trigger"]:disabled {
|
||||
border-color: var(--hm-select-border-color);
|
||||
background: var(--hm-select-background);
|
||||
opacity: var(--hm-select-disabled-opacity);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* Invalid belongs to the trigger border, never the popup surface or its neutral seam. */
|
||||
[data-slot="select-trigger"][aria-invalid="true"] {
|
||||
border-color: var(--hm-sem-action-destructive);
|
||||
}
|
||||
[data-slot="select-trigger"][aria-invalid="true"]:focus-visible {
|
||||
box-shadow: 0 0 0 3px color-mix(in srgb, var(--ring) 50%, transparent);
|
||||
}
|
||||
[data-slot="select-trigger"][aria-invalid="true"][data-state="open"][data-side="bottom"] {
|
||||
border-bottom-color: var(--hm-select-seam-color);
|
||||
}
|
||||
[data-slot="select-trigger"][aria-invalid="true"][data-state="open"][data-side="top"] {
|
||||
border-top-color: var(--hm-select-seam-color);
|
||||
}
|
||||
|
||||
/* List: same outer width as the trigger, border in the focus color, rounded only at the bottom (connected outline). */
|
||||
[data-slot="select-content"] {
|
||||
box-sizing: border-box;
|
||||
border: var(--hm-select-border-width) solid var(--hm-select-focus-border-color);
|
||||
border-radius: var(--hm-select-radius);
|
||||
background: var(--hm-select-background);
|
||||
color: var(--hm-select-text);
|
||||
box-shadow: var(--hm-select-content-shadow);
|
||||
}
|
||||
[data-slot="select-content"]:not([data-align-trigger="true"]) {
|
||||
width: var(--radix-select-trigger-width);
|
||||
min-width: var(--radix-select-trigger-width);
|
||||
}
|
||||
[data-slot="select-content"][data-side="bottom"] {
|
||||
border-radius: 0 0 var(--hm-select-radius) var(--hm-select-radius);
|
||||
/* sideOffset=-1 puts this top border on the trigger's bottom border, so it is the one seam line between the two.
|
||||
Only the seam is the quiet control border; the outer outline stays the focus color. */
|
||||
border-top-color: var(--hm-select-seam-color);
|
||||
}
|
||||
|
||||
[data-slot="select-content"][data-side="top"] {
|
||||
border-radius: var(--hm-select-radius) var(--hm-select-radius) 0 0;
|
||||
border-bottom-color: var(--hm-select-seam-color);
|
||||
}
|
||||
|
||||
/* Content uses the trigger's outer width. Its Viewport lives inside that bordered box, so it must fill the
|
||||
available inner width instead of applying the trigger's outer width as another minimum. */
|
||||
[data-slot="select-content"] [data-position="popper"] {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* Option profile follows the Select size: SelectContent carries data-size (from the Trigger, through context), the Portal
|
||||
keeps it out of the Trigger subtree. Width is not size-dependent (Content = Trigger outer width).
|
||||
Hover, Selected and Keyboard Active use the same face (set by the shadcn state classes). */
|
||||
[data-slot="select-content"] {
|
||||
--hm-select-option-height: var(--hm-select-option-height-lg);
|
||||
--hm-select-option-font-size: var(--hm-select-option-font-size-lg);
|
||||
--hm-select-option-line-height: var(--hm-select-option-line-height-lg);
|
||||
}
|
||||
[data-slot="select-content"][data-size="medium"] {
|
||||
--hm-select-option-height: var(--hm-select-option-height-md);
|
||||
--hm-select-option-font-size: var(--hm-select-option-font-size-md);
|
||||
--hm-select-option-line-height: var(--hm-select-option-line-height-md);
|
||||
}
|
||||
[data-slot="select-item"] {
|
||||
box-sizing: border-box;
|
||||
min-height: var(--hm-select-option-height);
|
||||
padding: 0 var(--hm-select-padding-x);
|
||||
border-radius: 0;
|
||||
font-size: var(--hm-select-option-font-size);
|
||||
line-height: var(--hm-select-option-line-height);
|
||||
font-weight: var(--hm-select-font-weight);
|
||||
}
|
||||
|
||||
/* ItemText: a flex item defaults to min-width:auto, so an unbreakable label kept its full width and pushed the row past the
|
||||
list (Item scrollWidth > Viewport clientWidth). Let it shrink to the row and truncate, like the trigger value. */
|
||||
[data-slot="select-item"] > span {
|
||||
display: block;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Radix keeps selection and the current pointer/keyboard highlight as separate states. ui_viz gives both
|
||||
the same option face, so use the actual Radix attributes rather than DOM position or focus alone. */
|
||||
[data-slot="select-item"][data-state="checked"],
|
||||
[data-slot="select-item"][data-highlighted] {
|
||||
background: var(--hm-select-option-state-background);
|
||||
color: var(--hm-select-option-state-text);
|
||||
}
|
||||
Reference in new issue
Block a user