Combobox
A versatile input component that combines a text input with a listbox, allowing users to filter a list of options and select single or multiple values.
Usage
import { Combobox } from "@chakra-ui/react"<Combobox.Root>
<Combobox.Label />
<Combobox.Control>
<Combobox.Input />
<Combobox.IndicatorGroup>
<Combobox.ClearTrigger />
<Combobox.Trigger />
</Combobox.IndicatorGroup>
</Combobox.Control>
<Combobox.Positioner>
<Combobox.Content>
<Combobox.Empty />
<Combobox.Item />
<Combobox.ItemGroup>
<Combobox.ItemGroupLabel />
<Combobox.Item />
</Combobox.ItemGroup>
</Combobox.Content>
</Combobox.Positioner>
</Combobox.Root>To setup combobox, you might need to import the following hooks:
-
useListCollection: Used to manage the list of items in the combobox, providing helpful methods for filtering and mutating the list. -
useFilter: Used to provide the filtering logic for the combobox based onIntl.CollatorAPIs.
Examples
Basic
The basic combobox provides a searchable dropdown with single selection.
Sizes
Pass the size prop to the Combobox.Root to change the size of the combobox.
Variants
Pass the variant prop to the Combobox.Root to change the appearance of the
combobox.
Multiple
Pass the multiple prop to the Combobox.Root to enable multiple selection.
This allows users to select multiple items from the list.
When this is set, the combobox will always clear the input value when an item is selected.
Async Loading
Here's an example of loading the collection asynchronously as users type,
perfect for API-driven search interfaces.
Highlight Matching Text
Here's an example of composing the Combobox.Item and Highlight components to
highlight matching text in search results.
Open on Click
Use the openOnClick prop to open the combobox when the user clicks on the
input.
Custom Objects
By default, the combobox collection expects an array of objects with label and
value properties. In some cases, you may need to deal with custom objects.
Use the itemToString and itemToValue props to map the custom object to the
required interface.
const items = [
{ country: "United States", code: "US", flag: "๐บ๐ธ" },
{ country: "Canada", code: "CA", flag: "๐จ๐ฆ" },
{ country: "Australia", code: "AU", flag: "๐ฆ๐บ" },
// ...
]
const { contains } = useFilter({ sensitivity: "base" })
const { collection } = useListCollection({
initialItems: items,
itemToString: (item) => item.country,
itemToValue: (item) => item.code,
filter: contains,
})Minimum Characters
Use the openOnChange prop to set a minimum number of characters before
filtering the list.
<Combobox.Root openOnChange={(e) => e.inputValue.length > 2} />Field
Compose the Combobox component with the Field component to wrap the combobox
in a form field. Useful for form layouts.
Form + Custom Object
When working with custom objects in forms, you often need to submit the programmatic value rather than the display value. This example shows how to combine custom object mapping with form submission using a hidden input.
The key is using itemToValue to define what gets submitted, while
itemToString controls what users see. A hidden input captures the programmatic
value for form submission.
In this example, users see "๐บ๐ธ United States" but the form submits "US".
Hook Form
This example demonstrates how to integrate the Combobox with React Hook Form
using the Controller component. The form automatically receives the item's
value property without needing a hidden input.
Users see "React" but the form receives "react".
Disabled State
Pass the disabled prop to the Combobox.Root to disable the entire combobox.
Disabled Item
Disable specific items in the dropdown, add the disabled prop to the
collection item.
const items = [
{ label: "Item 1", value: "item-1", disabled: true },
{ label: "Item 2", value: "item-2" },
]
const { collection } = useListCollection({
initialItems: items,
// ...
})Input Group
Combine with InputGroup to add icons or other elements.
Invalid
Pass the invalid prop to the Combobox.Root to show the error state.
Controlled Value
Use the value and onValueChange props to control the combobox's value
programmatically.
Store
An alternative way to control the combobox is to use the Combobox.RootProvider
component and the useCombobox store hook.
import { Combobox, useCombobox } from "@chakra-ui/react"
function Demo() {
const combobox = useCombobox()
return (
<Combobox.RootProvider value={combobox}>{/* ... */}</Combobox.RootProvider>
)
}This way you can access the combobox state and methods from outside the combobox.
Controlled Open
Use the open and onOpenChange props to control the combobox's open state
programmatically.
Limit Large Datasets
The recommended way of managing large lists is to use the limit property on
the useListCollection hook. This will limit the number of rendered items in
the DOM to improve performance.
Virtualization
Alternatively, you can leverage virtualization from the
@tanstack/react-virtual package to render large datasets efficiently.
Links
Use the asChild prop to render the combobox items as links.
For custom router links, you can customize the navigate prop on the
Combobox.Root component.
Here's an example of using the Tanstack Router.
import { Combobox } from "@chakra-ui/react"
import { useNavigate } from "@tanstack/react-router"
function Demo() {
const navigate = useNavigate()
return (
<Combobox.Root
navigate={({ href }) => {
navigate({ to: href })
}}
>
{/* ... */}
</Combobox.Root>
)
}Rehydrate Value
In some cases, where a combobox has a defaultValue but the collection is not
loaded yet, here's an example of how to rehydrate the value and populate the
input value.
Custom Item
Customize the appearance of items in the dropdown with your own components.
Audi
BMW
Citroen
Dacia
Fiat
Ford
Ferrari
Honda
Hyundai
Jaguar
Jeep
Kia
Land Rover
Mazda
Mercedes
Mini
Mitsubishi
Nissan
Opel
Peugeot
Porsche
Renault
Saab
Skoda
Subaru
Suzuki
Toyota
Volkswagen
VolvoCustom Filter
Here's an example of a custom filter that matches multiple properties of an item.
Custom Animation
To customize the animation of the combobox, pass the _open and _closed prop
to the Combobox.Content component.
Within Dialog
To use the combobox within a dialog or popover component, avoid wrapping the
Combobox.Positioner within the Portal.
-<Portal>
<Combobox.Positioner>
<Combobox.Content>
{/* ... */}
</Combobox.Content>
</Combobox.Positioner>
-</Portal>If you use a Dialog and have set scrollBehavior="inside", you need to:
- Set the combobox positioning to
fixedto avoid the combobox from being clipped by the dialog. - Set
hideWhenDetachedtotrueto hide the combobox when the trigger is scrolled out of view.
<Combobox.Root positioning={{ strategy: "fixed", hideWhenDetached: true }}>
{/* ... */}
</Combobox.Root>Creatable
Here's an example of how to allow users to create new options by typing values
that don't exist in the list. It uses the useCombobox and
Combobox.RootProvider components for smoother integration and management.
Note: This example is not fully tested. Feel free to use it as a starting point and improve it according to your needs.
Props
Root
| Prop | Default | Type |
|---|---|---|
collection * | ListCollection<T>The collection of items | |
composite | true | booleanWhether the combobox is a composed with other composite widgets like tabs |
defaultInputValue | | stringThe initial value of the combobox's input when rendered. Use when you don't need to control the value of the combobox's input. |
defaultValue | [] | string[]The initial value of the combobox's selected items when rendered. Use when you don't need to control the value of the combobox's selected items. |
inputBehavior | 'none' | 'none' | 'autohighlight' | 'autocomplete'Defines the auto-completion behavior of the combobox. - `autohighlight`: The first focused item is highlighted as the user types - `autocomplete`: Navigating the listbox with the arrow keys selects the item and the input is updated |
lazyMount | false | booleanWhether to enable lazy mounting |
loopFocus | true | booleanWhether to loop the keyboard navigation through the items |
openOnChange | true | boolean | ((details: InputValueChangeDetails) => boolean)Whether to show the combobox when the input value changes |
openOnClick | false | booleanWhether to open the combobox popup on initial click on the input |
openOnKeyPress | true | booleanWhether to open the combobox on arrow key press |
positioning | { placement: "bottom-start" } | PositioningOptionsThe positioning options to dynamically position the menu |
selectionBehavior | 'replace' | 'replace' | 'clear' | 'preserve'The behavior of the combobox input when an item is selected - `replace`: The selected item string is set as the input value - `clear`: The input value is cleared - `preserve`: The input value is preserved |
skipAnimationOnMount | false | booleanWhether to allow the initial presence animation. |
unmountOnExit | false | booleanWhether to unmount on exit. |
colorPalette | gray | 'gray' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'blue' | 'cyan' | 'purple' | 'pink'The color palette of the component |
variant | outline | 'outline' | 'subtle' | 'flushed'The variant of the component |
size | md | 'xs' | 'sm' | 'md' | 'lg'The size of the component |
as | React.ElementTypeThe underlying element to render. | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
unstyled | booleanWhether to remove the component's style. | |
allowCustomValue | booleanWhether to allow typing custom values in the input | |
autoFocus | booleanWhether to autofocus the input on mount | |
closeOnSelect | booleanWhether to close the combobox when an item is selected. | |
defaultHighlightedValue | stringThe initial highlighted value of the combobox when rendered. Use when you don't need to control the highlighted value of the combobox. | |
defaultOpen | booleanThe initial open state of the combobox when rendered. Use when you don't need to control the open state of the combobox. | |
disabled | booleanWhether the combobox is disabled | |
disableLayer | booleanWhether to disable registering this a dismissable layer | |
form | stringThe associate form of the combobox. | |
highlightedValue | stringThe controlled highlighted value of the combobox | |
id | stringThe unique identifier of the machine. | |
ids | Partial<{
root: string
label: string
control: string
input: string
content: string
trigger: string
clearTrigger: string
item: (id: string, index?: number | undefined) => string
positioner: string
itemGroup: (id: string | number) => string
itemGroupLabel: (id: string | number) => string
}>The ids of the elements in the combobox. Useful for composition. | |
immediate | booleanWhether to synchronize the present change immediately or defer it to the next frame | |
inputValue | stringThe controlled value of the combobox's input | |
invalid | booleanWhether the combobox is invalid | |
multiple | booleanWhether to allow multiple selection. **Good to know:** When `multiple` is `true`, the `selectionBehavior` is automatically set to `clear`. It is recommended to render the selected items in a separate container. | |
name | stringThe `name` attribute of the combobox's input. Useful for form submission | |
navigate | (details: NavigateDetails) => voidFunction to navigate to the selected item | |
onExitComplete | VoidFunctionFunction called when the animation ends in the closed state | |
onFocusOutside | (event: FocusOutsideEvent) => voidFunction called when the focus is moved outside the component | |
onHighlightChange | (details: HighlightChangeDetails<T>) => voidFunction called when an item is highlighted using the pointer or keyboard navigation. | |
onInputValueChange | (details: InputValueChangeDetails) => voidFunction called when the input's value changes | |
onInteractOutside | (event: InteractOutsideEvent) => voidFunction called when an interaction happens outside the component | |
onOpenChange | (details: OpenChangeDetails) => voidFunction called when the popup is opened | |
onPointerDownOutside | (event: PointerDownOutsideEvent) => voidFunction called when the pointer is pressed down outside the component | |
onSelect | (details: SelectionDetails) => voidFunction called when an item is selected | |
onValueChange | (details: ValueChangeDetails<T>) => voidFunction called when a new item is selected | |
open | booleanThe controlled open state of the combobox | |
placeholder | stringThe placeholder text of the combobox's input | |
present | booleanWhether the node is present (controlled by the user) | |
readOnly | booleanWhether the combobox is readonly. This puts the combobox in a "non-editable" mode but the user can still interact with it | |
required | booleanWhether the combobox is required | |
scrollToIndexFn | (details: ScrollToIndexDetails) => voidFunction to scroll to a specific index | |
translations | IntlTranslationsSpecifies the localized strings that identifies the accessibility elements and their states | |
value | string[]The controlled value of the combobox's selected items |
Item
| Prop | Default | Type |
|---|---|---|
as | React.ElementTypeThe underlying element to render. | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
item | anyThe item to render | |
persistFocus | booleanWhether hovering outside should clear the highlighted state |
Explorer
Explore the Combobox component parts interactively. Click on parts in the
sidebar to highlight them in the preview.
Component Anatomy
Hover to highlight, click to select parts
root
clearTrigger
content
control
input
item
itemGroup
itemGroupLabel
itemIndicator
itemText
label
list
positioner
trigger
empty
indicatorGroup