Skip to main content

Design system components

MultiCombobox

Multi-select combobox with inline chips, type-to-filter dropdown, label, error, and helper text.

Status: stable. Group: form. Markdown version: /design-system/components/multi-combobox.md

When to use

MultiCombobox picks several options from a list: chosen values render as removable Badge chips on one line inside the field (the ones that do not fit fold into a "+N" Badge), and the inline input filters the dropdown as you type. It is controlled (value: string[], onValueChange) and owns its label/error/helperText chrome. It shares field styling and dropdown mechanics with Combobox.

When not to use

  • Do not use for single-select; use Combobox instead.
  • Do not use it for exactly-one choice; Combobox and Select stay clearer and cheaper.

Look-alikes

  • Combobox: Do not use for single-select; use Combobox instead.
  • FilterChip: Do not use FilterChip for multi-select token input; use MultiCombobox.

Props

MultiCombobox props
PropTypeDefaultDescriptionRequired
labelstringnoneField label; associates the input.Yes
optionsMultiComboboxOption[]noneSelectable options.Yes
valuestring[]noneSelected values (controlled)Yes
onValueChange(value: string[]) => voidnoneCalled with the next selected values.Yes
idstringnoneExplicit control id (wires the label); auto-generated when omitted.No
placeholderstringnoneShown when nothing is selected.No
helperTextstringnoneAssistive text below the field.No
errorstringnoneError message; renders above the helper line and sets aria-invalid.No
statusFieldStatusnoneSemantic state: colours the border and styles statusMessage. error overrides it.No
statusMessagestringnoneMessage under the field for status, above the helper line.No
actionsFieldAction[]noneIcon buttons at the end of the label row: each runs an operation or opens a menu.No
requiredbooleanfalseMarks the field required.No
disabledbooleanfalseDisables the control.No
classNamestringnoneClasses on the field wrapper.No

Variants

No variant dimensions and no props with a fixed set of values.

Invalid combinations

The contract records no invalid combinations.

Keyboard

MultiCombobox keyboard behaviour
KeyBehaviour
TabMoves between the filter input and the toggle button; leaving the field closes an open list. Options are never Tab stops.
EnterActivates the focused control. (standard)
EscapeCloses or dismisses the open layer. (standard)
ArrowDownOpens the list, then moves the highlight to the next enabled option with wrap-around. Disabled options are skipped.
ArrowUpOpens the list, then moves the highlight to the previous enabled option with wrap-around. Disabled options are skipped.
BackspaceNamed in the contract without a description.

Rows marked (standard) name a key the contract lists without a description; the behaviour shown is the usual one for that key.

Rules

Every item under When not to use is a MUST NOT. MUST and SHOULD follow RFC 2119.

MultiCombobox rules
LevelRuleHow it is checked
MUSTARIA: Input role=combobox with aria-autocomplete=list, aria-expanded, aria-controls, aria-activedescendant.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: Labelled via aria-labelledby.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: Listbox role=listbox + aria-multiselectable + aria-label.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: Options role=option with aria-selected.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: Visible selected values are removable Badge chips; overflow folds into a +N Badge announced as "N more selected: <labels>"; Backspace on an empty filter removes the last value.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: Error sets aria-invalid + aria-describedby.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTRequired stories produce no axe violations at the configured severity.Automated by npm run test:stories:matrix:ci. WCAG 2.5.8.
MUSTThe accessibility tree (role, name, state) matches the committed snapshot for every required story.Automated by npm run test:stories:matrix:ci. WCAG 1.3.1, 4.1.2.
MUSTThe component remains legible and operable under a real browser forced-colors: active pass.Automated by npm run test:stories:hc.
MUSTEvery documented keyboard interaction works as specified.Not yet verified: no evidence record. WCAG 2.1.1, 2.1.2.
MUSTA human completed an end-to-end accessibility review of this component.Manual review, last on 2026-11-04.
SHOULDAlways control it: keep the selected values in state and hand back the full next array from onValueChange.Not stated in the contract.
SHOULDKeep option labels short; chips stay on one line, so long labels push more selections into the +N badge and a lone chip wider than the field truncates.Not stated in the contract.
SHOULDTell users about Backspace-to-remove in helperText for keyboard-heavy audiences; it deletes the last chip when the filter is empty.Not stated in the contract.
SHOULDCap the practical number of selections in your form validation and say so in helperText; selections that do not fit on one line are only summarised in the +N badge.Not stated in the contract.
SHOULD NOTDo not repurpose the chips as free-form tag creation; values must exist in options (no create-on-enter).Not stated in the contract.

Install and import

  • Install: npm install @digitaltableteur/react (version 0.9.1, restricted access on npm).
  • Import: import { MultiCombobox } from "@digitaltableteur/react";
  • Entry point: @digitaltableteur/react/forms exports it too.
  • Styles: import @digitaltableteur/react/style.css once at the app boundary.
  • Also available as the custom element <dt-multi-combobox>; see the custom elements manifest.