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
| Need | Use | Not |
|---|---|---|
| One value from a closed list (≈10 options or fewer) | Select — <Select> / .acrm-select-trigger | native <select>, a radio group with 10+ options |
| Several values from a closed list | Select 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 multiple | Record 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 allowed | Combobox, <datalist> |
| Search that hits the server as you type | Record select (async) | EntityPicker, ProductPicker |
| Picking a value inside a record rail | Record select anchored to the rail value | RailPickerMenu |
| Switching context in the top bar (pipeline, entity) | Nav select — <NavSelect> / .tchip | Select in the bar, a heading that opens a menu on its own |
| A menu of actions (not a value) | Picker menu — <PickerMenu> / .acrm-popover | Select, a kebab that renders its own menu |
Dropdown types
| Type | Anatomy | Package primitive | App pickers on it |
|---|---|---|---|
| A · plain menu | rows with optional 18px icon or stage dot, one line (ellipsis), accent check on the selected row, no trailing tag; closes on pick | PickerMenu, NavSelect, Select | RecordActionsMenu, ContextVariablesMenu, AccountingEntityPicker, TemplateMenu (under 10 templates) |
| B · search | sticky search row + list ≤ 264px + empty text; single value, check on the right | RecordSelect (single), Combobox (free text) | RailPickerMenu single (OwnerPickerEditor), TemplateMenu, DialCodePicker, RecordSearchSelect, AssignPicker, ProductPicker |
| C · multiselect | rows with the DS checkbox on the right; the menu stays open on toggle; optional reorder by drag | MultiSelect | CheckMenu (LayoutMenu, CategoryFilterChip), FilterBar |
| D · search + multi | B + C, selection pinned on top, hairline between groups, optional footer | RecordSelect multi | RailPickerMenu multi (TagsEditor), EntityPicker |
The story Components / Select → Dropdown types shows the four side by side.
Where each picker sits
| Picker | Type | Primitive it uses | Verdict |
|---|---|---|---|
Select (@acrm/ui) | A | .acrm-select-trigger + Popover + .acrm-popover-item .chk | canon |
MultiSelect (@acrm/ui) | C | .acrm-select-trigger + Popover + .acrm-checkbox right | canon |
Combobox (@acrm/ui) | B (free text) | .acrm-combobox + .acrm-combobox-pop via useAnchoredMenu | canon |
RecordSelect (@acrm/ui) | B / D | .acrm-recordselect-* via useAnchoredMenu | canon — 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 + PickerMenu | canon (composition) |
PickerMenu (@acrm/ui) | A | Popover + .acrm-popover-item | canon |
CheckMenu (components/CheckMenu.tsx, ds/check-menu.css) | C | Popover + .acrm-popover-item[menuitemcheckbox] + .acrm-checkbox right, .cm-reorder / .cm-drop-line | canon 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) | D | AddRefMenu shell (.acrm-popover.eref-add-pop, useAnchoredPanel) + .acrm-recordselect-search/-list/-opt rows; server typeahead | duplicate 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 V2 | duplicate shell — consolidation candidate (plan MR 15) |
RecordSearchSelect (components/RecordSearchSelect.tsx) | B | .acrm-recordselect trigger + AddRefMenu + record-select rows; server typeahead | duplicate — exists only because RecordSelect filters in memory; give RecordSelect async options and retire it (plan MR 15) |
AddRefMenu (components/AddRefMenu.tsx) | shell for B/D | createPortal + useAnchoredPanel, .acrm-popover.eref-add-pop | duplicate of Popover + useAnchoredMenu — consolidation candidate |
DialCodePicker (components/multivalue/DialCodePicker.tsx) | B | Popover 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-empty | composition — fine (.mc-tplstick keeps the search row sticky) |
LayoutMenu (components/record/LayoutMenu.tsx) | C | CheckMenu with onReorder | composition — fine |
ContextVariablesMenu (pages/settings/ContextVariablesMenu.tsx) | A | Popover + .acrm-popover-item (tag removed 28 Sep 2026) | composition — fine |
AccountingEntityPicker (components/accounting/AccountingEntityPicker.tsx) | A | NavSelect; SectionTopBarChip when there is one entity | composition — fine |
AssignPicker (components/mail/AssignPicker.tsx) | B | bespoke .rcpt-menu / .rcpt-opt (mail.css) via createPortal + useAnchoredPanel | duplicate — consolidation candidate (plan MR 7) |
PlaudPickerDialog (components/meetings/PlaudPickerDialog.tsx) | — | Dialog + ItemList + .acrm-checkbox | not a dropdown; a dialog list — fine, outside the family |
OwnerPickerEditor (components/record/OwnerPickerEditor.tsx) | B | RailPickerMenu mode="single" | composition — fine |
RecordActionsMenu (components/record/RecordActionsMenu.tsx) | A | Popover + .acrm-popover-item (.danger last) | composition — fine |
TagsEditor (components/TagsEditor.tsx) | D | RailPickerMenu mode="multi" + .rpk-create footer | composition — 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 whatPopoveranduseAnchoredMenualready do. Plan MR 7 and MR 15 fold them into type B. - One row:
DialCodePickerrows (.phe-ccrow) should become.acrm-popover-item(the code in the name, no trailing tag). - One check:
RecordSelectsingle should draw.acrm-recordselect-cklikeRailPickerMenu— a checkbox promises multi-select (F261). - Async options on
RecordSelectremove the reason forRecordSearchSelect. CheckMenuandRailPickerMenuare canonical by anatomy but live app-side; the catalog renders their markup, not the components.- Zero native selects is the target:
ChannelsPopoverEditortype 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-popover 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;.subdescriptions removed 21 Aug 2026; the trailing.tagremoved 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);RecordSelectin the package still draws a checkbox in single mode (F261 alignment pending). The card's "text-only" Record select rows have no package prop —RecordSelectalways renders an avatar; the text-only row exists inRailPickerMenu(avataromitted). The card's "Nadpis-dropdown (s ikonou)" is the.pipe-btnscreen 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
- Select · accessibility — closed list, single or
multiple - Record select · accessibility — searchable records, single or multiple, optional free text
- Nav select · accessibility — context switch in the top bar
- Picker menu · accessibility — menu of actions
Deprecated — listed for migration, never for new work
| Deprecated | Replace with | Usages to migrate |
|---|---|---|
| Multi-select | Select with multiple | 1 (PersonRail) |
| Combobox | Record select with free text | 1 (ChartAccountDialogs) |
| Check menu | Select with multiple / Record select multi | 2 |
| Rail picker | Record select anchored in a rail row | 2 |
| Entity picker | Record select with async search | 12 |
| Product picker | Record select, async, products | 2 |
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.