Combobox
A single input field that combines the functionality of a select and input.
A single input field that combines the functionality of a select and input.
To set up the combobox correctly, you’ll need to understand its anatomy and how we name its parts.
Each part includes a
data-partattribute to help identify them in the DOM.
Learn how to use the Combobox component in your project. Let’s take a look at
the most basic example
import { Combobox, Portal } from '@ark-ui/react'
export const Basic = () => {
const items = ['React', 'Solid', 'Vue']
return (
<Combobox.Root items={items} lazyMount unmountOnExit>
<Combobox.Label>Framework</Combobox.Label>
<Combobox.Control>
<Combobox.Input />
<Combobox.Trigger>Open</Combobox.Trigger>
<Combobox.ClearTrigger>Clear</Combobox.ClearTrigger>
</Combobox.Control>
<Portal>
<Combobox.Positioner>
<Combobox.Content>
<Combobox.ItemGroup>
<Combobox.ItemGroupLabel>Frameworks</Combobox.ItemGroupLabel>
{items.map((item) => (
<Combobox.Item key={item} item={item}>
<Combobox.ItemText>{item}</Combobox.ItemText>
<Combobox.ItemIndicator>✓</Combobox.ItemIndicator>
</Combobox.Item>
))}
</Combobox.ItemGroup>
</Combobox.Content>
</Combobox.Positioner>
</Portal>
</Combobox.Root>
)
}
import { For } from 'solid-js'
import { Portal } from 'solid-js/web'
import { Combobox } from '@ark-ui/solid'
export const Basic = () => {
const items = ['React', 'Solid', 'Vue']
return (
<Combobox.Root items={items} multiple>
<Combobox.Label>Framework</Combobox.Label>
<Combobox.Control>
<Combobox.Input />
<Combobox.Trigger>Open</Combobox.Trigger>
<Combobox.ClearTrigger>Clear</Combobox.ClearTrigger>
</Combobox.Control>
<Portal>
<Combobox.Positioner>
<Combobox.Content>
<Combobox.ItemGroup>
<Combobox.ItemGroupLabel>Frameworks</Combobox.ItemGroupLabel>
<For each={items}>
{(item) => (
<Combobox.Item item={item}>
<Combobox.ItemText>{item}</Combobox.ItemText>
<Combobox.ItemIndicator>✓</Combobox.ItemIndicator>
</Combobox.Item>
)}
</For>
</Combobox.ItemGroup>
</Combobox.Content>
</Combobox.Positioner>
</Portal>
</Combobox.Root>
)
}
<script setup lang="ts">
import { ref } from 'vue'
import { Combobox } from '@ark-ui/vue'
const items = ref(['React', 'Solid', 'Vue'])
</script>
<template>
<Combobox.Root :items="items">
<Combobox.Label>Framework</Combobox.Label>
<Combobox.Control>
<Combobox.Input />
<Combobox.Trigger>Open</Combobox.Trigger>
<Combobox.ClearTrigger>Clear</Combobox.ClearTrigger>
</Combobox.Control>
<Teleport to="body">
<Combobox.Positioner>
<Combobox.Content>
<Combobox.ItemGroup>
<Combobox.ItemGroupLabel>Frameworks</Combobox.ItemGroupLabel>
<Combobox.Item v-for="item in items" :key="item" :item="item">
<Combobox.ItemText>{{ item }}</Combobox.ItemText>
<Combobox.ItemIndicator>✓</Combobox.ItemIndicator>
</Combobox.Item>
</Combobox.ItemGroup>
</Combobox.Content>
</Combobox.Positioner>
</Teleport>
</Combobox.Root>
</template>
Extended example that shows usage with complex item objects, including disabled state for certain options.
import { Combobox, Portal } from '@ark-ui/react'
export const Advanced = () => {
const items = [
{ label: 'React', value: 'react' },
{ label: 'Solid', value: 'solid' },
{ label: 'Vue', value: 'vue' },
{ label: 'Svelte', value: 'svelte', disabled: true },
]
return (
<Combobox.Root items={items} multiple>
<Combobox.Label>Framework</Combobox.Label>
<Combobox.Control>
<Combobox.Input />
<Combobox.Trigger>Open</Combobox.Trigger>
<Combobox.ClearTrigger>Clear</Combobox.ClearTrigger>
</Combobox.Control>
<Portal>
<Combobox.Positioner>
<Combobox.Content>
<Combobox.ItemGroup>
<Combobox.ItemGroupLabel>Frameworks</Combobox.ItemGroupLabel>
{items.map((item) => (
<Combobox.Item key={item.value} item={item}>
<Combobox.ItemText>{item.label}</Combobox.ItemText>
<Combobox.ItemIndicator>✓</Combobox.ItemIndicator>
</Combobox.Item>
))}
</Combobox.ItemGroup>
</Combobox.Content>
</Combobox.Positioner>
</Portal>
</Combobox.Root>
)
}
import { For } from 'solid-js'
import { Portal } from 'solid-js/web'
import { Combobox } from '@ark-ui/solid'
export const Advanced = () => {
const items = [
{ label: 'React', value: 'react' },
{ label: 'Solid', value: 'solid' },
{ label: 'Vue', value: 'vue' },
{ label: 'Svelte', value: 'svelte', disabled: true },
]
return (
<Combobox.Root items={items}>
<Combobox.Label>Framework</Combobox.Label>
<Combobox.Control>
<Combobox.Input />
<Combobox.Trigger>Open</Combobox.Trigger>
<Combobox.ClearTrigger>Clear</Combobox.ClearTrigger>
</Combobox.Control>
<Portal>
<Combobox.Positioner>
<Combobox.Content>
<Combobox.ItemGroup>
<Combobox.ItemGroupLabel>Frameworks</Combobox.ItemGroupLabel>
<For each={items}>
{(item) => (
<Combobox.Item item={item}>
<Combobox.ItemText>{item.label}</Combobox.ItemText>
<Combobox.ItemIndicator>✓</Combobox.ItemIndicator>
</Combobox.Item>
)}
</For>
</Combobox.ItemGroup>
</Combobox.Content>
</Combobox.Positioner>
</Portal>
</Combobox.Root>
)
}
<script setup lang="ts">
import { ref } from 'vue'
import { Combobox } from '@ark-ui/vue'
const advancedItems = ref([
{ label: 'React', value: 'react' },
{ label: 'Solid', value: 'solid' },
{ label: 'Vue', value: 'vue' },
{ label: 'Svelte', value: 'svelte', disabled: true },
])
</script>
<template>
<Combobox.Root :items="advancedItems" multiple>
<Combobox.Label>Framework</Combobox.Label>
<Combobox.Control>
<Combobox.Input />
<Combobox.Trigger>Open</Combobox.Trigger>
<Combobox.ClearTrigger>Clear</Combobox.ClearTrigger>
</Combobox.Control>
<Teleport to="body">
<Combobox.Positioner>
<Combobox.Content>
<Combobox.ItemGroup>
<Combobox.ItemGroupLabel>Frameworks</Combobox.ItemGroupLabel>
<Combobox.Item v-for="item in advancedItems" :key="item.value" :item="item">
<Combobox.ItemText>{{ item.label }}</Combobox.ItemText>
<Combobox.ItemIndicator>✓</Combobox.ItemIndicator>
</Combobox.Item>
</Combobox.ItemGroup>
</Combobox.Content>
</Combobox.Positioner>
</Teleport>
</Combobox.Root>
</template>
Under the hood for React and Solid frameworks, we supply a complex prop type
with a generic so that the type of the items prop matches the param type in
the function signatures for props such as the isItemDisabled prop, say. (See
the api reference table below) Unfortunately, generic typing is not supported in
Vue for components that contain props with slots and/or emits. Therefore, you
will not expect updated typing in this way.
If you have a solution or a workaround to this problem, we would love the contribution and request that you open a Github idea discussion to let us know a PoC you have to share!
| Prop | Type | Default |
|---|---|---|
itemsThe options of the select | T[] | readonly T[] | |
allowCustomValueWhether to allow typing custom values in the input | boolean | |
asChildRender as a different element type. | boolean | |
autoFocusWhether to autofocus the input on mount | boolean | |
closeOnSelectWhether to close the combobox when an item is selected. | boolean | |
defaultOpenThe initial open state of the combobox when it is first rendered.
Use when you do not need to control its open state. | boolean | |
defaultValueThe initial value of the combobox when it is first rendered.
Use when you do not need to control the state of the combobox. | string[] | |
disabledWhether the combobox is disabled | boolean | |
dismissableWhether to register this combobox as a dismissable layer | boolean | |
formThe associate form of the combobox. | string | |
getSelectionValueFunction to get the display value of the selected item | (details: SelectionValueDetails<T>) => string | |
highlightedValueThe active item's id. Used to set the `aria-activedescendant` attribute | string | |
idThe unique identifier of the machine. | string | |
idsThe ids of the elements in the combobox. Useful for composition. | 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
}> | |
inputBehaviorDefines 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 | 'none' | 'autohighlight' | 'autocomplete' | |
inputValueThe current value of the combobox's input | string | |
invalidWhether the combobox is required | boolean | |
isItemDisabledWhether the item is disabled | (item: T) => boolean | |
itemToStringThe label of the item | (item: T) => string | |
itemToValueThe value of the item | (item: T) => string | |
lazyMountWhether to enable lazy mounting | boolean | false |
loopFocusWhether to loop the keyboard navigation through the items | boolean | |
multipleWhether to allow multiple selection | boolean | |
nameThe `name` attribute of the combobox's input. Useful for form submission | string | |
onExitCompleteFunction called when the animation ends in the closed state. | () => void | |
onFocusOutsideFunction called when the focus is moved outside the component | (event: FocusOutsideEvent) => void | |
onHighlightChangeFunction called when an item is highlighted using the pointer
or keyboard navigation. | (details: HighlightChangeDetails<T>) => void | |
onInputValueChangeFunction called when the input's value changes | (details: InputValueChangeDetails) => void | |
onInteractOutsideFunction called when an interaction happens outside the component | (event: InteractOutsideEvent) => void | |
onOpenChangeFunction called when the popup is opened | (details: OpenChangeDetails) => void | |
onPointerDownOutsideFunction called when the pointer is pressed down outside the component | (event: PointerDownOutsideEvent) => void | |
onValueChangeFunction called when a new item is selected | (details: ValueChangeDetails<T>) => void | |
openWhether the combobox is open | boolean | |
openOnChangeWhether to show the combobox when the input value changes | boolean | ((details: InputValueChangeDetails) => boolean) | |
openOnClickWhether to open the combobox popup on initial click on the input | boolean | |
openOnKeyPressWhether to open the combobox on arrow key press | boolean | |
placeholderThe placeholder text of the combobox's input | string | |
popupThe underling `aria-haspopup` attribute to use for the combobox
- `listbox`: The combobox has a listbox popup (default)
- `dialog`: The combobox has a dialog popup. Useful when in select only mode | 'dialog' | 'listbox' | |
positioningThe positioning options to dynamically position the menu | PositioningOptions | |
presentWhether the node is present (controlled by the user) | boolean | |
readOnlyWhether the combobox is readonly. This puts the combobox in a "non-editable" mode
but the user can still interact with it | boolean | |
scrollToIndexFnFunction to scroll to a specific index | (details: ScrollToIndexDetails) => void | |
selectionBehaviorThe 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 | 'replace' | 'clear' | 'preserve' | |
translationsSpecifies the localized strings that identifies the accessibility elements and their states | IntlTranslations | |
unmountOnExitWhether to unmount on exit. | boolean | false |
valueThe keys of the selected items | string[] |
| Prop | Type | Default |
|---|---|---|
asChildRender as a different element type. | boolean |
| Prop | Type | Default |
|---|---|---|
asChildRender as a different element type. | boolean |
| Prop | Type | Default |
|---|---|---|
asChildRender as a different element type. | boolean |
| Prop | Type | Default |
|---|---|---|
asChildRender as a different element type. | boolean |
| Prop | Type | Default |
|---|---|---|
asChildRender as a different element type. | boolean |
| Prop | Type | Default |
|---|---|---|
asChildRender as a different element type. | boolean |
| Prop | Type | Default |
|---|---|---|
asChildRender as a different element type. | boolean |
| Prop | Type | Default |
|---|---|---|
asChildRender as a different element type. | boolean | |
itemThe item to render | any | |
persistFocusWhether hovering outside should clear the highlighted state | boolean |
| Prop | Type | Default |
|---|---|---|
asChildRender as a different element type. | boolean |
| Prop | Type | Default |
|---|---|---|
asChildRender as a different element type. | boolean |
| Prop | Type | Default |
|---|---|---|
asChildRender as a different element type. | boolean |
| Prop | Type | Default |
|---|---|---|
asChildRender as a different element type. | boolean |
Previous
Color PickerNext
Date Picker