Combobox

A searchable select: type to filter, pick one or many, or load options from a server as the user types.

StableSource

Import

import { Combobox, type ComboboxOption } from "@meridui/react";

Examples

Multiple

multiple keeps the list open after each pick and shows the selection as chips. value becomes a string[]. Backspace in an empty field removes the last chip.

Next.jsVite

Pick any number.

value: ["next","vite"]

Async options

Fetch from onInputValueChange, pass the results as options, set filter={false} so the component does not filter again, and toggle loading while the request runs. Labels of chosen options are remembered, so chips and the field keep their text when the results change.

Sizes and states

API reference

Renders a div wrapper; other div attributes go on it. aria-label and aria-labelledby go on the text field. Inside a Field the field picks up the id, label, description, error, required and disabled.

PropTypeDefaultDescription
optionsRequiredComboboxOption[]–{ value, label, description?, disabled? }. Replace them as async results arrive.
multiplebooleanfalseSelect many values, shown as chips.
valuestring | string[]–Controlled value: a string ("" for none), or string[] with multiple.
defaultValuestring | string[]–Initial value when uncontrolled.
onValueChange(value) => void–Called with the new value.
inputValuestring–Controlled text in the field.
defaultInputValuestring–Initial text. Defaults to the selected label.
onInputValueChange(text: string) => void–Called on every keystroke; fetch async options here.
open / defaultOpen / onOpenChangeboolean / boolean / (open) => void–Controlled or initial open state of the list.
filter((option, text) => boolean) | falselabel contains textClient-side filter. false when options are already filtered.
localestring–Locale for case-insensitive matching, e.g. "tr-TR" so İ and i match.
loadingbooleanfalseShows loadingMessage and sets aria-busy on the list.
placeholderstring–Placeholder of the text field.
emptyMessageReactNode"No results"Shown when nothing matches.
loadingMessageReactNode"Loading…"Shown while loading.
toggleLabelstring"Show options"Accessible name of the chevron button.
getRemoveLabel(label: string) => stringRemove {label}Accessible name of a chip's remove button.
size"sm" | "md" | "lg""md"Control size.
invalidboolean–aria-invalid and the danger border. Inside a Field, derived from its error.
disabledboolean–Disables the combobox.
requiredboolean–Marks the field required.
namestring–Form name. Renders one hidden input per selected value.
inputIdstring–id of the text field, for a <label htmlFor>.
placementPlacement"bottom-start"Preferred list placement.
containerElement | nulldocument.bodyPortal target of the list.
inputRefRef<HTMLInputElement>–Ref to the text field.
refRef<HTMLDivElement>–Ref to the wrapper.

Styling

ClassElement
.mrd-comboboxWrapper (data-size, data-state, data-multiple, data-invalid, data-disabled)
.mrd-combobox__controlBordered field holding chips, input and toggle
.mrd-combobox__input, .mrd-combobox__toggleText field, chevron button
.mrd-combobox__chip, .mrd-combobox__chip-removeSelected value chip (multiple)
.mrd-combobox__content, .mrd-combobox__listboxPortalled popup and its listbox
.mrd-combobox__itemOption (data-active, data-disabled, aria-selected)
.mrd-combobox__statusLoading / empty message

Accessibility

Follows the WAI-ARIA Combobox pattern with a listbox popup and list autocomplete. Focus stays in the text field; the highlighted option is exposed with aria-activedescendant. The loading and empty messages are a role="status" region, so they are announced. Chip remove buttons are skipped by Tab; use Backspace in the empty field, or the pointer.

KeyAction
ArrowDownOpen the list, or highlight the next option (wraps).
ArrowUpOpen the list at the last option, or highlight the previous option (wraps).
AltArrowDownOpen without moving the highlight.
EnterSelect the highlighted option. Single: closes. Multiple: toggles and stays open.
EscapeClose the list; single mode restores the selected label.
BackspaceMultiple, empty field: remove the last chip.
TabClose and move on.

Guidelines

Do

Use Combobox when the list is long (20+ items) or comes from a server, and people know what they are looking for.

Avoid

Use it for a handful of options; a Select or Radio is faster to scan.

  • Select — pick one from a short, fixed list.
  • Field — label, hint and error around a control.