Select

Two field types — Select for a closed list, Record select for a searchable list of records; both with an optional multiple mode. Never a native select.

AD 2. 9. 2026 (review ACRM-76–81, picks ACRM-105): the four approved dropdown types A–D are two axes (search yes/no x multiple yes/no), so the family has two field components, not six. Multi-select = Select with multiple; Combobox = Record select with free text; Check menu, Rail picker, Entity picker and Product picker are usages of those two, not elements of their own. Nav select (context switch in the top bar) and Picker menu (action menu, not a field) stay separate.

7 sub-components · 71% covered

Sub-components

  • Selectcanon✓✓✓✓✓✓Single or multiple choice from a closed list (roughly ten options or fewer); 32px field trigger opening the type A menu.
  • Record selectcanon✓✓✓✓✓✓Search-driven choice from records: framed field, or panel anchored to a rail row or a chip. Sections separated by a named hairline, one value = accent check.
  • Nav selectcanon✓✓✓✓✓✓Compact chip-style select used inside top bars to switch views.
  • Picker menucanon✓✓✓✓✓✓Anchored menu of items with optional check marks and icons.
  • Check menucanon✓✓✓✓✓✓The one menu for toggling a set of options (columns, tiles, categories): checkbox on the right, optional search, hidden items below a line, reorder by drag or Alt+↑/↓; bottom sheet with Hotovo on a phone.
  • Entity pickerbeta–✓✓✓––Record reference field: removable record chips plus Add, built on the canonical RecordSelect (server search, recent, create from e-mail).
  • Product pickerbeta–✓✓✓––Product field: product chips plus Add, built on the canonical RecordSelect in adding mode, with free text.

Shared usage

Two field types, not six (AD decision, 2 Sep 2026 — review ACRM-76–81, pick ACRM-105). The four approved dropdown types A–D (Petr, 21 Aug 2026 — docs/PLAN-dropdown-sjednoceni.md in acrm) are two axes — search yes/no × multiple yes/no — so the family has Select (closed list) and Record select (searchable list of records), each with a multiple mode, plus Nav select (context switch in the top bar, different trigger) and Picker menu (action menu, not a field).

Everything else that used to be its own entry is a mode or a usage of those two and is now deprecated: MultiSelect = Select with multiple (1 usage), Combobox = Record select with free text (1 usage), CheckMenu = the multiple mode drawn as a menu (2), RailPickerMenu = Record select anchored in a rail row (2), EntityPicker = Record select with async search (12), ProductPicker = the same limited to products (2). They stay listed until their usages are migrated; nothing new is built on them. Rule that binds the family (docs/DS-USAGE.md): dropdowns are always the DS popover, never a native <select>.

Values measured from apps/web/src/ds.css and apps/web/src/ds/inputs.css on main: shell .acrm-popover (or .acrm-recordselect-pop for search panels) = --surface-100, 1px --border-strong, --radius-md, --shadow-pop, padding --sp-2, z-index 101 over a scrim at 85; row = 500 13px/20px var(--font-sans), padding --sp-2 --sp-3 → 32px, hover --hover-surface; select-one check = .chk in --accent, hidden with visibility; multi = .acrm-checkbox 16px, 1.5px --border-strong, --radius-xs, on the RIGHT; search row = borderless input 400 14px, 18px icon, hairline --border below; list scrolls inside max-height: 264px. Field triggers (.acrm-select-trigger, .acrm-recordselect-trigger, .acrm-combobox) are 32px, --radius-sm, open state = --accent border + 3px accent halo (16%). Top-bar trigger .tchip = --control-h 30px, --radius-md, --shadow-xs, open = --active-surface.

Which field for which need

NeedUseNot
One value from a closed list (≈10 options or fewer)Select — <Select> / .acrm-select-triggernative <select>, a radio group with 10+ options
Several values from a closed listSelect with multiple (checkbox on the right, menu stays open)MultiSelect, a bespoke checkbox menu, several selects
More than ~10 items, or records (people, companies, products), single or multipleRecord select — <RecordSelect> (search row, list ≤ 264px)Select with a long list, an ad-hoc dropdown
Free text with suggestions (address, ARES)Record select with free text allowedCombobox, <datalist>
Search that hits the server as you typeRecord select (async)EntityPicker, ProductPicker
Picking a value inside a record railRecord select anchored to the rail valueRailPickerMenu
Switching context in the top bar (pipeline, entity)Nav select — <NavSelect> / .tchipSelect in the bar, a heading that opens a menu on its own
A menu of actions (not a value)Picker menu — <PickerMenu> / .acrm-popoverSelect, a kebab that renders its own menu
TypeAnatomyPackage primitiveApp pickers on it
A · plain menurows with optional 18px icon or stage dot, one line (ellipsis), accent check on the selected row, no trailing tag; closes on pickPickerMenu, NavSelect, SelectRecordActionsMenu, ContextVariablesMenu, AccountingEntityPicker, TemplateMenu (under 10 templates)
B · searchsticky search row + list ≤ 264px + empty text; single value, check on the rightRecordSelect (single), Combobox (free text)RailPickerMenu single (OwnerPickerEditor), TemplateMenu, DialCodePicker, RecordSearchSelect, AssignPicker, ProductPicker
C · multiselectrows with the DS checkbox on the right; the menu stays open on toggle; optional reorder by dragMultiSelectCheckMenu (LayoutMenu, CategoryFilterChip), FilterBar
D · search + multiB + C, selection pinned on top, hairline between groups, optional footerRecordSelect multiRailPickerMenu multi (TagsEditor), EntityPicker

The story Components / Select → Dropdown types shows the four side by side.

Where each picker sits

PickerTypePrimitive it usesVerdict
Select (@acrm/ui)A.acrm-select-trigger + Popover + .acrm-popover-item .chkcanon
MultiSelect (@acrm/ui)C.acrm-select-trigger + Popover + .acrm-checkbox rightcanon
Combobox (@acrm/ui)B (free text).acrm-combobox + .acrm-combobox-pop via useAnchoredMenucanon
RecordSelect (@acrm/ui)B / D.acrm-recordselect-* via useAnchoredMenucanon — single mode still draws .acrm-checkbox, not the F261 accent check .acrm-recordselect-ck that RailPickerMenu emits; align in the package
NavSelect (@acrm/ui)A.tchip + PickerMenucanon (composition)
PickerMenu (@acrm/ui)APopover + .acrm-popover-itemcanon
CheckMenu (components/CheckMenu.tsx, ds/check-menu.css)CPopover + .acrm-popover-item[menuitemcheckbox] + .acrm-checkbox right, .cm-reorder / .cm-drop-linecanon type C, app-side — promote to the package when a second consumer outside the app appears
RailPickerMenu (components/RailPickerMenu.tsx)B / D.acrm-recordselect-pop/-search/-list/-opt, .acrm-popover-sep, useAnchoredMenu; anchor .rr-ev.rpk-anchor, footer .rpk-foot (record-rail.css)canon in the rail (F194/F195) — composition of canonical rows, no own shell
EntityPicker (components/EntityPicker.tsx)DAddRefMenu shell (.acrm-popover.eref-add-pop, useAnchoredPanel) + .acrm-recordselect-search/-list/-opt rows; server typeaheadduplicate shell — rows are canonical, shell and anchoring re-implement Popover/useAnchoredMenu; consolidation candidate (plan MR 15)
ProductPicker (components/ProductPicker.tsx)B (+ free-text row)same as EntityPicker (AddRefMenu + record-select rows), group heading pending AD gate V2duplicate shell — consolidation candidate (plan MR 15)
RecordSearchSelect (components/RecordSearchSelect.tsx)B.acrm-recordselect trigger + AddRefMenu + record-select rows; server typeaheadduplicate — exists only because RecordSelect filters in memory; give RecordSelect async options and retire it (plan MR 15)
AddRefMenu (components/AddRefMenu.tsx)shell for B/DcreatePortal + useAnchoredPanel, .acrm-popover.eref-add-popduplicate of Popover + useAnchoredMenu — consolidation candidate
DialCodePicker (components/multivalue/DialCodePicker.tsx)BPopover shell + .acrm-recordselect-search; rows .phe-ccrow (multi-value.css)partial — shell canonical (plan MR 10), rows bespoke; consolidation candidate
TemplateMenu (components/mail/compose/TemplateMenu.tsx)B (A under 10)Popover + .acrm-recordselect-search + .acrm-popover-item, .acrm-popover-emptycomposition — fine (.mc-tplstick keeps the search row sticky)
LayoutMenu (components/record/LayoutMenu.tsx)CCheckMenu with onReordercomposition — fine
ContextVariablesMenu (pages/settings/ContextVariablesMenu.tsx)APopover + .acrm-popover-item (tag removed 28 Sep 2026)composition — fine
AccountingEntityPicker (components/accounting/AccountingEntityPicker.tsx)ANavSelect; SectionTopBarChip when there is one entitycomposition — fine
AssignPicker (components/mail/AssignPicker.tsx)Bbespoke .rcpt-menu / .rcpt-opt (mail.css) via createPortal + useAnchoredPanelduplicate — consolidation candidate (plan MR 7)
PlaudPickerDialog (components/meetings/PlaudPickerDialog.tsx)—Dialog + ItemList + .acrm-checkboxnot a dropdown; a dialog list — fine, outside the family
OwnerPickerEditor (components/record/OwnerPickerEditor.tsx)BRailPickerMenu mode="single"composition — fine
RecordActionsMenu (components/record/RecordActionsMenu.tsx)APopover + .acrm-popover-item (.danger last)composition — fine
TagsEditor (components/TagsEditor.tsx)DRailPickerMenu mode="multi" + .rpk-create footercomposition — fine
ChannelsPopoverEditor (components/multivalue/ChannelsPopoverEditor.tsx)A (type cell)native <select class="phe-type">native — violation; the only native select left in the app (the ds-ok comment argues the box does not fit the row — the fix is a quiet type A trigger, not a native control)

Consolidation notes

  • One shell: AddRefMenu + useAnchoredPanel (EntityPicker, ProductPicker, RecordSearchSelect) and .rcpt-menu (AssignPicker) re-implement what Popover and useAnchoredMenu already do. Plan MR 7 and MR 15 fold them into type B.
  • One row: DialCodePicker rows (.phe-ccrow) should become .acrm-popover-item (the code in the name, no trailing tag).
  • One check: RecordSelect single should draw .acrm-recordselect-ck like RailPickerMenu — a checkbox promises multi-select (F261).
  • Async options on RecordSelect remove the reason for RecordSearchSelect.
  • CheckMenu and RailPickerMenu are canonical by anatomy but live app-side; the catalog renders their markup, not the components.
  • Zero native selects is the target: ChannelsPopoverEditor type cell is the last one.

Legacy card Inputs — what still holds

Harvested from legacy/Inputs.html ("Výběr & rozbalovací nabídky", "Rozbalovací nabídky") and legacy/popover.html, checked against apps/web/src/ds.css and apps/web/src/ds/inputs.css:

  • Still true: "No headings inside menus — never an eyebrow above the items; the only exception is a hairline group separator." "Menu, combobox and popover carry --shadow-pop over a hairline ring and --radius-md." "The active item in a single select carries the check on the right; in a multi select the filled checkbox on the right (D6, 22 Aug 2026)." "Record select opens with a search box on top (hairline), the list scrolls inside 264px; use it whenever the list has more than ~10 items." "The LIST scrolls, not the panel — a scrolling panel with a sticky header produced F257." "One-line items 500 13/20 → 32px; .sub descriptions removed 21 Aug 2026; the trailing .tag removed 28 Sep 2026 (ACRM-375–377) — a row is its name only." "Fields are flat at rest; the shadow belongs to the open menu." Record select variants "single (check, closes on pick) · text-only (no avatar, code lists) · in menu (no trigger, search is the first row) · search without list (hairline disappears)".
  • Superseded or ahead of code: the card's Record select "single" check is only implemented app-side (RailPickerMenu); RecordSelect in the package still draws a checkbox in single mode (F261 alignment pending). The card's "text-only" Record select rows have no package prop — RecordSelect always renders an avatar; the text-only row exists in RailPickerMenu (avatar omitted). The card's "Nadpis-dropdown (s ikonou)" is the .pipe-btn screen switch (family Section top bar), not a member of this family. The registry summary "native select on mobile" for Select is not in code — the native element is sr-only form backing on every viewport.

Sub-components

Current

Deprecated — listed for migration, never for new work

DeprecatedReplace withUsages to migrate
Multi-selectSelect with multiple1 (PersonRail)
ComboboxRecord select with free text1 (ChartAccountDialogs)
Check menuSelect with multiple / Record select multi2
Rail pickerRecord select anchored in a rail row2
Entity pickerRecord select with async search12
Product pickerRecord select, async, products2

Migration order (largest first): Entity picker → Product picker → Check menu → Rail picker → Multi-select → Combobox. Each step is a separate merge request; the deprecated entry disappears from the registry once its last usage is gone.