Combobox
A single input field that combines the functionality of a select and input.
Anatomy
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.
Examples
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>
Advanced Customization
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>
API Reference
Root
| Prop | Default | Type | 
|---|---|---|
items | T[] | readonly T[]The options of the select  | |
allowCustomValue | booleanWhether to allow typing custom values in the input  | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
autoFocus | booleanWhether to autofocus the input on mount  | |
closeOnSelect | booleanWhether to close the combobox when an item is selected.  | |
composite | true | booleanWhether the combobox is a composed with other composite widgets like tabs  | 
defaultOpen | booleanThe initial open state of the combobox when it is first rendered. Use when you do not need to control its open state.  | |
defaultValue | string[]The initial value of the combobox when it is first rendered. Use when you do not need to control the 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.  | |
getSelectionValue | (details: SelectionValueDetails<T>) => stringFunction to get the display value of the selected item  | |
highlightedValue | stringThe active item's id. Used to set the `aria-activedescendant` attribute  | |
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  | |
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  | 
inputValue | stringThe current value of the combobox's input  | |
invalid | booleanWhether the combobox is invalid  | |
isItemDisabled | (item: T) => booleanWhether the item is disabled  | |
itemToString | (item: T) => stringThe label of the item  | |
itemToValue | (item: T) => stringThe value of the item  | |
lazyMount | false | booleanWhether to enable lazy mounting  | 
loopFocus | true | booleanWhether to loop the keyboard navigation through the items  | 
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  | |
onExitComplete | () => voidFunction 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  | |
onValueChange | (details: ValueChangeDetails<T>) => voidFunction called when a new item is selected  | |
open | booleanWhether the combobox is open  | |
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  | 
placeholder | stringThe placeholder text of the combobox's input  | |
positioning | PositioningOptionsThe positioning options to dynamically position the menu  | |
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  | |
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  | 
translations | IntlTranslationsSpecifies the localized strings that identifies the accessibility elements and their states  | |
unmountOnExit | false | booleanWhether to unmount on exit.  | 
value | string[]The keys of the selected items  | 
| Data Attribute | Value | 
|---|---|
[data-scope] | combobox | 
[data-part] | root | 
[data-invalid] | Present when invalid | 
[data-readonly] | Present when read-only | 
ClearTrigger
| Prop | Default | Type | 
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | 
Content
| Prop | Default | Type | 
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | 
| Data Attribute | Value | 
|---|---|
[data-scope] | combobox | 
[data-part] | content | 
[data-state] | "open" | "closed" | 
Control
| Prop | Default | Type | 
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | 
| Data Attribute | Value | 
|---|---|
[data-scope] | combobox | 
[data-part] | control | 
[data-state] | "open" | "closed" | 
[data-focus] | Present when focused | 
[data-disabled] | Present when disabled | 
[data-invalid] | Present when invalid | 
Input
| Prop | Default | Type | 
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | 
| Data Attribute | Value | 
|---|---|
[data-scope] | combobox | 
[data-part] | input | 
[data-invalid] | Present when invalid | 
[data-state] | "open" | "closed" | 
ItemGroupLabel
| Prop | Default | Type | 
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | 
ItemGroup
| Prop | Default | Type | 
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | 
ItemIndicator
| Prop | Default | Type | 
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | 
| Data Attribute | Value | 
|---|---|
[data-scope] | combobox | 
[data-part] | item-indicator | 
[data-state] | "checked" | "unchecked" | 
Item
| Prop | Default | Type | 
|---|---|---|
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  | 
| Data Attribute | Value | 
|---|---|
[data-scope] | combobox | 
[data-part] | item | 
[data-highlighted] | Present when highlighted | 
[data-state] | "checked" | "unchecked" | 
[data-disabled] | Present when disabled | 
[data-value] | 
ItemText
| Prop | Default | Type | 
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | 
| Data Attribute | Value | 
|---|---|
[data-scope] | combobox | 
[data-part] | item-text | 
[data-disabled] | Present when disabled | 
[data-highlighted] | Present when highlighted | 
Label
| Prop | Default | Type | 
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | 
| Data Attribute | Value | 
|---|---|
[data-scope] | combobox | 
[data-part] | label | 
[data-readonly] | Present when read-only | 
[data-disabled] | Present when disabled | 
[data-invalid] | Present when invalid | 
[data-focus] | Present when focused | 
List
| Prop | Default | Type | 
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | 
Positioner
| Prop | Default | Type | 
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | 
RootProvider
| Prop | Default | Type | 
|---|---|---|
value | UseComboboxReturn<T> | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
immediate | booleanWhether to synchronize the present change immediately or defer it to the next frame  | |
lazyMount | false | booleanWhether to enable lazy mounting  | 
onExitComplete | () => voidFunction called when the animation ends in the closed state  | |
present | booleanWhether the node is present (controlled by the user)  | |
unmountOnExit | false | booleanWhether to unmount on exit.  | 
Trigger
| Prop | Default | Type | 
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
focusable | booleanWhether the trigger is focusable  | 
| Data Attribute | Value | 
|---|---|
[data-scope] | combobox | 
[data-part] | trigger | 
[data-state] | "open" | "closed" | 
[data-focusable] | |
[data-readonly] | Present when read-only | 
[data-disabled] | Present when disabled | 
Accessibility
Complies with the Combobox WAI-ARIA design pattern.
Keyboard Support
| Key | Description | 
|---|---|
ArrowDown  | When the combobox is closed, opens the listbox and highlights to the first option. When the combobox is open, moves focus to the next option. | 
ArrowUp  | When the combobox is closed, opens the listbox and highlights to the last option. When the combobox is open, moves focus to the previous option. | 
Home  | When the combobox is open, moves focus to the first option. | 
End  | When the combobox is open, moves focus to the last option. | 
Escape  | Closes the listbox. | 
Enter  | Selects the highlighted option and closes the combobox. | 
Esc  | Closes the combobox |