Select
One value from a closed short list (≤ ~10 items). React <Select> (packages/ui/src/components/Select.tsx) renders a 32px field trigger .acrm-select-trigger (apps/web/src/ds/inputs.css §5) that opens the portalled DS <Popover> (.acrm-popover, apps/web/src/ds.css) with .acrm-popover-item rows and an accent check on the selected row — dropdown type A. It is never the native OS menu: a hidden select.acrm-select-native (sr-only, position: fixed) only backs the form (name, required, FormData, constraint validation).
When to use
- One value from a closed list of up to ~10 options: country, pipeline, type, status.
- A form field that must submit with the form (
name,required) — the hidden native select carries it. - A drop-in replacement for an existing native
<select>: the API keeps<option>children,valueandonChange(e)withe.target.value.
When not to use
- More than ~10 items or records (people, companies) — use Record select (search row).
- Several values — use Multi-select.
- Free text with suggestions from an external source (address, ARES) — use Combobox.
- A view/sort/filter switch in a section top bar — use Nav select (
.tchip). - A native
<select>for the visible control — flagged bypnpm ds:validate:usage; the only allowed native select is the sr-only backing one inside this component.
Anatomy
- Trigger
button.acrm-select-trigger:display: flex,width: 100%,height: 32px,padding: 0 var(--sp-3),gap: var(--sp-3),background: var(--surface-100),border: 1px solid var(--border-strong),border-radius: var(--radius-sm),font: var(--p),color: var(--ink-900); hover--surface-75. - Value
.acrm-select-val(ellipsis) + 16px chevron in--fg-muted. - States on the trigger:
.is-placeholder=--fg-mutedtext;.is-open=--accentborder +0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent);.is-error=--criticalborder + 16% halo;:disabled=--surface-75,--border,--fg-muted, no shadow;.is-select-ignored= muted text (import mapping). - Menu
.acrm-popover:position: fixed,z-index: 101over a scrim at 85,min-width: 180px,max-width: min(360px, 100vw − 16px),max-height: min(60vh, 420px),padding: var(--sp-2),--surface-100,1px --border-strong,--radius-md,--shadow-pop; width = trigger width (offsetWidth). - Row
button.acrm-popover-item[role=option]:font: 500 13px/20px,padding: var(--sp-2) var(--sp-3)→ 32px,--radius-sm, hover--hover-surface;.tx > .nm(ellipsis) +.chk(accent,--ico-xs) hidden withvisibilitywhen.off;:disabled=opacity: 0.4. - Hidden
select.acrm-select-native:tabindex=-1,aria-hidden, 1×1px,clip-path: inset(50%). - No header, no eyebrow above the rows; groups only by
.acrm-popover-sep(1px--border,margin: var(--sp-1) 0).
Best practices
Do
- Wrap the field in
<Field label>; the label is the accessible name viaaria-labelledby, or passaria-labelfor a bare trigger. - Keep the option label short and final — one line, no description; no secondary identifier, no trailing tag and no second line (no grey trailing tag (owner 28 Sep 2026, ACRM-375–377)).
- Let the trigger take the width of its container (
width: 100%) and size the container to the longest option. - Pass
placeholder(or an empty-value<option>) when the field can be unset; an uncontrolled select withoutdefaultValuepicks the first option like a native select.
Don't
- A
<Select>with 20 countries or 40 users — it has no search; that is Record select. is-openstyling on hover or a shadow on the resting trigger — fields are flat at rest, elevation belongs to the open menu only.- An eyebrow or title inside the menu ("Pipeline") — the trigger's label already says it.
- A colour fill for the selected row — selection is the accent check on a plain row.
Content
- Trigger placeholder: an imperative with an ellipsis — "Vyberte…" (default), "Vyberte pipeline…"; sentence case.
- Options are nouns in sentence case, no trailing period, no "Please select".
- Error text goes under the field in
.acrm-field-error, not into the trigger; the trigger only getsclassName="is-error". - Dates in options follow the DS year rule ("26. 8." / "14. 11. 27"); numbers stay proportional, never
tabular-nums.
Related
multi-select— same trigger, checkbox rows, menu stays open.record-select— search row for > ~10 items or records.combobox— free text with suggestions.picker-menu— the same type A rows on any trigger.popover(family Popover) — the shell.- Stories:
components--select--default,components--select--states,components--select--composition,components--select--dropdown-types(types A–D side by side); legacycomponents--inputs--select.
Several values — multiple (acrm !4472, 3 Oct 2026)
Picking several values from the same closed list is a prop of Select, not a separate component („vícenásobný výběr je prop, ne komponenta“). It replaced MultiSelect, which is gone.
- Same trigger and menu as the single select. Each row carries the DS checkbox on the right (
.acrm-checkbox); the menu stays open after a click so the user can tick several items. - The value is an array of keys in the order they were picked (a new pick goes to the end); changes come through
onValuesChange(values). The hidden native select ismultiple, soonChange(e)and form submission keep working. - The trigger summarises the choice: one or two labels joined („A, B“), three and more as „N vybráno“, or your own
summary(selected). Empty shows the placeholder. - Use it for short closed lists (roughly up to 10 items). A long or searchable list is
RecordSelectwith chips (adding mode), notSelect multiple.
Source: docs/select/select.usage.md · GitLab