MultiSelect

Searchable multi-value select with a popover listbox, chips and grouping

Category: inputs · WCAG 2.2-AA · form, select, multi, input, popover, combobox, tags

Sizes

States

Props

PropTypeDefaultDescription
optionsMultiSelectOption[]—The selectable options.
valuestring[]—The controlled value. Omit it and pass defaultValue to let the component own the selection.
defaultValuestring[][]The initial value when uncontrolled.
onValueChange(value: string[]) => void—Called with the new value when it changes.
placeholderstring—Placeholder text shown when the field is empty.
labelstring—Visible field label, rendered above the trigger.
ariaLabelstring—Invisible accessible name, for when a visible element outside this component already labels it and `label` would render that text a second time. ⚠ `label` on this component is **visible**; `IconButton.label`/`Sparkline.label` are invisible names, which is the prior that costs adopters a duplicated label.
aria-labelledbystring—Wired automatically by a wrapping `Field` — its label id, forwarded to the focusable control so the Field's label names it.
aria-describedbystring—Wired automatically by a wrapping `Field` — the ids of its hint/error text, forwarded to the focusable control so the supporting text is announced.
aria-invalidboolean—Wired automatically by a wrapping `Field` when it is in an error state.
hintstring—Helper text below the field.
errorstring—Error text below the field; also marks the control invalid.
display'count' | 'chips''count'How the trigger summarises the selection: a count, or one removable chip per value.
disabledbooleanfalseWhen true, disables the control and removes it from the tab order.
clearablebooleanfalseWhen true, shows a control that clears every selected value.
selectAllbooleanfalseWhen true, shows a row that selects or clears every enabled option at once.
maxnumber—Maximum number of values that may be selected. Further options become unselectable once reached.
creatablebooleanfalseWhen true, offers the current search text as a new option.
onCreate(label: string) => void—Called with the typed label when the user picks the "create" row.
loadingbooleanfalseWhen true, the list reports itself as busy and shows a loading row instead of the no-results message.
onSearchChange(query: string) => void—Called with the search text on every keystroke. Pair it with filter={() => true} for a server-driven list.
filter(option: MultiSelectOption, query: string) => boolean—Replaces the built-in diacritic-insensitive matcher.
searchablebooleantrueWhen true, shows the search field. The list is keyboard-navigable either way.
size'sm' | 'md' | 'lg''md'Field height.
namestring—Submitted with a surrounding form — one hidden input per selected value.
labelsMultiSelectLabels—Overrides for the component’s user-visible strings (i18n).
idstring—Id for the trigger control.

Design tokens

When to use

When not to use

How to build an accessible MultiSelect in React →

Examples

Basic

<MultiSelect options={[{label:'One',value:'1'},{label:'Two',value:'2'}]} defaultValue={[]} />

Chips with a clear control

Each selection renders as a chip with its own remove button.

<MultiSelect options={options} display="chips" clearable defaultValue={['1']} />

Grouped options

Options carrying a group render under a labelled role="group" heading.

<MultiSelect options={[{label:'Apple',value:'a',group:'Pome'},{label:'Cherry',value:'c',group:'Stone'}]} />

Remote search

filter={() => true} hands filtering to the server; loading marks the list busy between keystroke and response.

<MultiSelect options={results} loading={pending} onSearchChange={search} filter={() => true} />

Bounded selection

Options past the limit report aria-disabled; select-all stops at the limit.

<MultiSelect options={options} max={3} selectAll />

Related components

← Back to docs