Combobox
Free text with suggestions from an external source (address, ARES, city). React <Combobox> (packages/ui/src/components/Combobox.tsx) is a 32×240px field .acrm-combobox (leading icon + borderless input) with a portalled suggestion list ul.acrm-combobox-pop positioned by useAnchoredMenu — dropdown type B in its free-text form. The caller owns the text (value / onInputChange), fetches options and receives the chosen suggestion via onSelect.
When to use
- The typed text is itself a valid value and suggestions only help: street, city, company name from ARES.
- The suggestion source is external or too big to load: the caller fetches on every keystroke (debounce in the caller).
- One field, one line, a secondary identifier per suggestion (postcode, ICO) rendered in
.psc.
When not to use
- Picking an existing record (person, company, user) — the value must be an id, use Record select.
- A closed list of ≤ ~10 values — use Select.
- Several values — Record select
multior Tag input; Combobox holds one string. - A search field that filters a list on the page — that is the top-bar
.tsearch, not a combobox.
Anatomy
- Field
.acrm-combobox:display: flex,height: 32px,width: 240px,max-width: 100%,--surface-100,1px --border-strong,--radius-sm;.is-open=--accentborder + 3px 16% halo (only while suggestions or the empty text show). - Leading icon slot
.ti(default 16px search glyph,leadingIconprop for map-pin, building…):padding-left: var(--sp-3),--fg-secondary,--ico-sm. - Input:
border: 0,outline: none,font: 500 13px var(--font-sans),color: var(--fg),padding: 0 var(--sp-3); placeholder--fg-muted. - Suggestions
ul.acrm-combobox-pop(portal,position: fixed,z-index: 101fromuseAnchoredMenu, flips up at the viewport bottom):padding: var(--sp-2),max-height: 264px, scroll,--surface-100,1px --border-strong,--radius-md,--shadow-pop. - Row
li.acrm-combobox-opt[role=option]:gap: var(--sp-3),padding: var(--sp-2) var(--sp-3)→ 32px,--radius-sm;.is-active=--hover-surface;.nm500 13px/20px--fg(ellipsis) +.psc500 12px--fg-mutedon the right.renderOptionreplaces the row content. - Empty
li.acrm-combobox-empty:padding: var(--sp-3), centered, 400 13px--fg-muted— shown only whenemptyTextis set and the input is not blank. - No check mark, no checkbox: the row is a suggestion, not a selection state.
Best practices
Do
- Debounce the fetch in the caller and pass the latest
options; the component highlights the first suggestion on every new query. - Give every suggestion a
sub(postcode, city, ICO) so two similar streets can be told apart on one line. - Set
emptyText("Nic nenalezeno") when the source can answer "no match"; leave it unset while the source is just slow. - Use a
leadingIconthat names the source (map-pin for address, building for ARES).
Don't
- A combobox for records that must resolve to an id — the user can leave free text that matches nothing.
- Widening the field to 100% by default — width follows the typical content (240px); wrap it in a container when a form row needs it wider.
- Two-line suggestions or a heading inside the list — one line with
.psc, groups only by need (none in code). - A native
<datalist>— the DS popup is the only suggestion list.
Content
- Placeholder describes what to type: "Ulice a číslo…", "Název firmy nebo IČO…"; sentence case, ellipsis.
.psccarries a short identifier (postcode "110 00", city, ICO) — no labels like "PSČ:".- Empty text is one short sentence in
--fg-muted: "Nic nenalezeno" — no advice on how to search. - Postcodes keep the Czech space ("110 00"); numbers proportional, not mono.
Related
record-select— id-based choice with search.select— closed short list.text-field(family Text field) — the plain input the combobox extends.- Stories:
components--combobox--default,components--combobox--variants(row content),components--combobox--states(rest, filled, open, open empty),components--combobox--with-icon-kbd(leading icons),components--combobox--composition.
Source: docs/select/combobox.usage.md · GitLab