Combobox

A popover with a searchable list, for picking one value or several.

Single selection

Compose Combobox.Root, a trigger, and Combobox.Content holding a Combobox.Command. Combobox.Input filters the rows of Combobox.List as you type, and Combobox.Empty shows when nothing matches. Mark the chosen row with a check in end and close the popover in onSelect.

Inside a form, use fullSizeAndButtonWithChevronToTheRight with w-full for a field-sized trigger, and fullWidth on the content so the list matches the trigger's width.

Answer engine

Multiple selection

Combobox.ItemCheckbox adds a checkbox to the row and keeps the popover open while you toggle. Hovering a row shows an only button; handle it with onOnlyClick to select that row alone, or pass showOnlyButton={false} to hide it.

A controlled Combobox.Input with onClear and clearLabel shows a clear button once there is a query. Put footer actions after the list behind a Combobox.Separator alwaysRender, so the divider stays while the list is filtered.

Groups

Combobox.Group takes a heading. Search hides a group once none of its rows match. Add the group name to each row's keywords so searching for the group finds its rows.

Trigger variants

buttonWithChevron renders a compact button with a chevron that flips while the list is open; pass mode="ghost" for an inline switcher in a header. Short lists can skip the input; pass shouldFilter={false} to Combobox.Command when there is nothing to filter. With asChild, any button opens the list, which suits actions such as adding a person.

Usage

Search matches each row's value and keywords. When results come from the server, pass shouldFilter={false} to Combobox.Command, control the input with value and onValueChange, and render only the rows you get back. While they load, set loading on Combobox.Input to swap the search icon for a spinner, or render Combobox.Loading inside the list.

Combobox.Root is non-modal by default. Inside a drawer or a modal dialog it is always modal, so a long list can still scroll.

Combobox.Item with href renders a link row; Enter and click both navigate. For long lists, ComboboxVirtualList from @repo/design-system/components/primitives/combobox/virtual-list renders only the visible rows.

Combobox.Root Properties

open
boolean

Controlled open state of the popover

defaultOpen
boolean

Initial open state when uncontrolled

Default: false

onOpenChange
(open: boolean) => void

Called when the open state changes

modal
boolean

Traps focus and blocks the page behind the list. Always true inside a drawer or a modal dialog

Default: false

Combobox.Trigger Properties

asChild
boolean

Merges the trigger behavior into its child element, such as a Button

Default: false

buttonWithChevron
boolean

Renders a Button with a chevron that flips while the list is open

Default: false

fullSizeAndButtonWithChevronToTheRight
boolean

Renders a field-style Button with a truncated label on the left and the chevron on the right

Default: false

iconStart
IconValue

Button variants only. Icon name, descriptor, or node before the label

customIconEnd
IconValue

Button variants only. Replaces the chevron

hideChevron
boolean

Button variants only. Hides the chevron

Default: false

size
'micro''small''regular''large'

Button variants only. buttonWithChevron defaults to small, the full-size variant to regular

mode
ButtonMode

Button variants only. Button style, such as ghost or dashed

Default: secondary

loading
{ isLoading: boolean }

Button variants only. The full-size variant shows a spinner in place of the chevron and is disabled

disabled
boolean

Whether the trigger is disabled

Default: false

childrenClassName
string

Full-size variant only. Classes for the label wrapper

contentClassName
string

Button variants only. Classes for the Button's inner content

Combobox.Content Properties

size
number

Minimum width of the popover in pixels

Default: 249

fullWidth
boolean

Uses the trigger's width as the minimum width instead of size

Default: false

align
'start''center''end'

Alignment of the popover relative to the trigger

Default: center

side
'top''right''bottom''left'

Preferred side of the trigger to render against

Default: bottom

sideOffset
number

Distance in pixels from the trigger

Default: 10

alignOffset
number

Offset in pixels along the alignment axis

Default: 0

withRadixPortal
boolean

Renders the popover in a portal. Set to false to render it in place

Default: true

portalProps
PopoverPortalProps

Props for the portal, such as container

animateClose
boolean

Fades the popover out on close. Turn off when picking an option shifts the layout underneath

Default: true

Combobox.Command Properties

shouldFilter
boolean

Filters and sorts rows by the input's query. Set to false when you filter the rows yourself

Default: true

filter
(value: string, search: string, keywords?: string[]) => number

Custom ranking. Return 0 to hide a row, higher numbers to rank it first

loop
boolean

Arrow keys wrap from the last row to the first

Default: true

value
string

Controlled value of the highlighted row

onValueChange
(value: string) => void

Called when the highlighted row changes

label
string

Accessible label for the command menu

Combobox.Input Properties

placeholder
string

Placeholder text

value
string

Controlled query

onValueChange
(search: string) => void

Called when the query changes

loading
boolean

Shows a spinner in place of the search icon

Default: false

onClear
() => void

Shows a clear button while value is not empty. Requires clearLabel

clearLabel
string

Accessible label for the clear button. Required with onClear

classNameWrapper
string

Classes for the row that holds the icon and the input

Combobox.List Properties

height
numberstring

Maximum height before the list scrolls. Numbers are pixels; strings are any CSS length

Default: 300

Combobox.Item Properties

value
string

Unique value used for search and highlighting. Defaults to the row's text

keywords
string[]

Extra terms that match the row in search

onSelect
(value: string) => void

Called when the row is clicked or chosen with Enter

disabled
boolean

Whether the row is disabled

Default: false

start
IconValue

Icon name, descriptor, or node before the label

end
IconValue

Icon name, descriptor, or node at the end of the row, such as a check for the chosen row

href
string

Renders the row as a link. Enter and click both navigate

prefetch
boolean

With href. Forwarded to Next.js Link

Default: true

onNavigate
() => void

With href. Called as the row starts navigating in this tab

disableTooltip
boolean

Turns off the tooltip that shows a truncated label in full

Default: false

tooltipSide
'top''right''bottom''left'

Side of the truncated-label tooltip

childrenClassName
string

Classes for the label wrapper

Combobox.ItemCheckbox Properties

checkedRequired
boolean

Whether the row is checked

onSelect
(value: string) => void

Called when the row is toggled

showOnlyButton
boolean

Shows an only button on hover

Default: true

onOnlyClick
() => void

Called when the only button is clicked

checkboxDisabledReason
string

Locks the checkbox and explains why in a tooltip. The row stays interactive

value
string

Unique value used for search and highlighting

keywords
string[]

Extra terms that match the row in search

disabled
boolean

Whether the row is disabled

Default: false

start
IconValue

Icon name, descriptor, or node between the checkbox and the label

end
IconValue

Icon name, descriptor, or node after the label

disableTooltip
boolean

Renders the label without truncation, for labels that own their layout

Default: false

Combobox.Group and Combobox.Separator Properties

heading
ReactNode

Group only. Heading shown above the group's rows

forceMount
boolean

Group only. Keeps the group rendered when search matches none of its rows

Default: false

alwaysRender
boolean

Separator only. Keeps the separator while there is a query. Without it, separators hide during search

Default: false

Other Parts

Combobox.Empty
ComponentPropsWithoutRef<typeof Command.Empty>

Shown when search matches no row

Combobox.Loading
ComponentPropsWithoutRef<typeof Command.Loading>

Loading row for async results. Takes label and progress

Combobox.Label
ComponentPropsWithoutRef<'span'> & { size?: 'small' | 'medium' }

Standalone heading outside a group. size defaults to small

Combobox.StandaloneButton
ComponentPropsWithoutRef<'button'> & { start?: IconValue; end?: IconValue }

Button styled like a row, for actions below the list

Combobox.StandaloneLink
LinkProps & { start?: IconValue; end?: IconValue }

Link styled like a row, for navigation below the list