Installation
Theme
Mode

Forms & input

Combobox

A searchable single-select for when a plain dropdown is too long — assignees, projects, labels. Type to filter, navigate with the keyboard, and clear in a click. Built on Base UI for filtering, keyboard navigation, and ARIA combobox semantics.

$npx shadcn@latest add @orbit/combobox

Overview

Click to open, type to filter, ↑↓ to move, Enter to pick.

Assignee

Datasets

The same component adapts its option rows to the data — avatars for people, icons for projects, colour dots for labels. Pass any ReactNode as an item's lead and a secondary sub line.

People
Projects
Labels

Preselected & controlled

Pass defaultValue for an uncontrolled initial selection, or value + onValueChange to control it. Clearing calls onValueChange(null).

Controlled

value: "priya"

Sizes

sm 32px · md 38px (default, spec) · lg 44px.

Small · 32px
Medium · 38px
Large · 44px

States

Error switches the border and focus ring to the danger tokens and sets aria-invalid. Disabled flattens to a neutral treatment and hides the clear affordance.

Error
Disabled
Disabled with value
Not clearable

Empty results

When nothing matches the query the list shows an empty message — customise it with emptyMessage.

Type a name that doesn't exist
No options at all

Props

PropTypeDefaultDescription
itemsComboboxItem[]Options to pick from. See the item shape below.
labelstringField label rendered above the control.
placeholderstring"Select…"Text shown in the closed field when nothing is selected.
searchPlaceholderstring"Search…"Placeholder of the search input inside the popup.
emptyMessagestring"No matches"Message shown when no option matches the query.
valuestring | nullSelected item value. Use with onValueChange for a controlled combobox.
defaultValuestring | nullInitial selection when uncontrolled.
onValueChange(value: string | null) => voidCalled with the selected item's value, or null when cleared.
clearablebooleantrueShows a clear affordance in the field while a value is selected.
size"sm" | "md" | "lg""md"Control height: 32 / 38 / 44px.
errorbooleanfalseDanger border + focus ring, sets aria-invalid.
disabledbooleanfalseBlocks interaction and flattens the field.
namestringIdentifies the field when a form is submitted.
classNamestringClass applied to the outer wrapper.
PropTypeDefaultDescription
ComboboxItem.valuestringUnique value identifying the option.
ComboboxItem.labelstringRow label; also what the search filter matches.
ComboboxItem.substringSecondary line under the label — role, team, count.
ComboboxItem.leadReactNodeLeading visual — avatar, icon, or colour dot.
ComboboxItem.disabledbooleanfalseRenders the option non-interactive.

Usage

Reach for a combobox when a select would exceed ~8 options. For a handful of fixed choices use a Select; for multiple values use a token input.

Do

Use it past ~8 options

When a list is long enough to scroll, search beats scanning. Below that, a plain Select is simpler.

Don’t

Use it for multi-select

One value per combobox. For tags or multiple assignees, use a token / multi-select input instead.

Do

Show a secondary line

Role, team or count under the label disambiguates similar names and speeds recognition.

Don’t

Hide the current value

Always render the selection in the closed field, with its avatar or icon, so state is obvious at rest.

Keyboard & accessibility

Full ARIA combobox semantics from Base UI: the trigger is a button labelled by the field label, the popup search input controls the listbox, and the highlighted option is announced. Hands never leave the keyboard.

Enter / ↓Open the menu
TypeFilter options
↑ ↓Move the highlight
EnterSelect the highlighted option
EscClose the menu
Tab to the field, press Enter, type, ↑↓, Enter
Assignee