Components
Combobox

Combobox

A single input field that combines the functionality of a select and input.

You can explore the combobox component in the following curated examples.

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-part attribute 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, createListCollection } from '@ark-ui/solid/combobox'
import { For, createMemo, createSignal } from 'solid-js'
import { Portal } from 'solid-js/web'

const initialItems = ['React', 'Solid', 'Vue']

export const Basic = () => {
  const [items, setItems] = createSignal(initialItems)

  const collection = createMemo(() => createListCollection({ items: items() }))

  const handleInputChange = (details: Combobox.InputValueChangeDetails) => {
    setItems(
      initialItems.filter((item) => item.toLowerCase().includes(details.inputValue.toLowerCase())),
    )
  }

  return (
    <Combobox.Root collection={collection()} onInputValueChange={handleInputChange}>
      <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={collection().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>
  )
}

Advanced Customization

Extended example that shows usage with complex item objects, including disabled state for certain options.

import { Combobox, createListCollection } from '@ark-ui/solid/combobox'
import { For } from 'solid-js'
import { Portal } from 'solid-js/web'

export const Advanced = () => {
  const collection = createListCollection({
    items: [
      { label: 'React', value: 'react' },
      { label: 'Solid', value: 'solid' },
      { label: 'Vue', value: 'vue' },
      { label: 'Svelte', value: 'svelte', disabled: true },
    ],
  })
  return (
    <Combobox.Root collection={collection}>
      <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={collection.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>
  )
}

Using the Field Component

The Field component helps manage form-related state and accessibility attributes of a combobox. It includes handling ARIA labels, helper text, and error text to ensure proper accessibility.

import { Combobox, createListCollection } from '@ark-ui/solid/combobox'
import { Field } from '@ark-ui/solid/field'
import { For } from 'solid-js'

export const WithField = (props: Field.RootProps) => {
  const collection = createListCollection({ items: ['React', 'Solid', 'Vue'] })

  return (
    <Field.Root {...props}>
      <Combobox.Root collection={collection}>
        <Combobox.Label>Label</Combobox.Label>
        <Combobox.Control>
          <Combobox.Input />
          <Combobox.Trigger>Open</Combobox.Trigger>
          <Combobox.ClearTrigger>Clear</Combobox.ClearTrigger>
        </Combobox.Control>
        <Combobox.Positioner>
          <Combobox.Content>
            <For each={collection.items}>
              {(item) => (
                <Combobox.Item item={item}>
                  <Combobox.ItemText>{item}</Combobox.ItemText>
                  <Combobox.ItemIndicator>✓</Combobox.ItemIndicator>
                </Combobox.Item>
              )}
            </For>
          </Combobox.Content>
        </Combobox.Positioner>
      </Combobox.Root>
      <Field.HelperText>Additional Info</Field.HelperText>
      <Field.ErrorText>Error Info</Field.ErrorText>
    </Field.Root>
  )
}

Using the Root Provider

The RootProvider component provides a context for the combobox. It accepts the value of the useCombobox hook. You can leverage it to access the component state and methods from outside the combobox.

import { Combobox, createListCollection, useCombobox } from '@ark-ui/solid/combobox'
import { For, createMemo, createSignal } from 'solid-js'
import { Portal } from 'solid-js/web'

const initialItems = ['React', 'Solid', 'Vue']

export const RootProvider = () => {
  const [items, setItems] = createSignal(initialItems)

  const collection = createMemo(() => createListCollection({ items: items() }))

  const handleInputChange = (details: Combobox.InputValueChangeDetails) => {
    setItems(
      initialItems.filter((item) => item.toLowerCase().includes(details.inputValue.toLowerCase())),
    )
  }

  const combobox = useCombobox({ collection: collection(), onInputValueChange: handleInputChange })

  return (
    <>
      <button onClick={() => combobox().focus()}>Focus</button>

      <Combobox.RootProvider value={combobox}>
        <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={collection().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.RootProvider>
    </>
  )
}

If you're using the RootProvider component, you don't need to use the Root component.

API Reference

Root

PropDefaultType
collection
ListCollection<T>

The collection of items

allowCustomValue
boolean

Whether to allow typing custom values in the input

asChild
(props: ParentProps<'div'>) => Element

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
autoFocus
boolean

Whether to autofocus the input on mount

closeOnSelect
boolean

Whether to close the combobox when an item is selected.

compositetrue
boolean

Whether the combobox is a composed with other composite widgets like tabs

defaultOpen
boolean

The 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
boolean

Whether the combobox is disabled

disableLayer
boolean

Whether to disable registering this a dismissable layer

form
string

The associate form of the combobox.

highlightedValue
string

The active item's id. Used to set the `aria-activedescendant` attribute

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
boolean

Whether to synchronize the present change immediately or defer it to the next frame

inputBehavior'none'
'none' | 'autocomplete' | 'autohighlight'

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
string

The current value of the combobox's input

invalid
boolean

Whether the combobox is invalid

lazyMountfalse
boolean

Whether to enable lazy mounting

loopFocustrue
boolean

Whether to loop the keyboard navigation through the items

multiple
boolean

Whether 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
string

The `name` attribute of the combobox's input. Useful for form submission

onExitComplete
() => void

Function called when the animation ends in the closed state

onFocusOutside
(event: FocusOutsideEvent) => void

Function called when the focus is moved outside the component

onHighlightChange
(details: HighlightChangeDetails<T>) => void

Function called when an item is highlighted using the pointer or keyboard navigation.

onInputValueChange
(details: InputValueChangeDetails) => void

Function called when the input's value changes

onInteractOutside
(event: InteractOutsideEvent) => void

Function called when an interaction happens outside the component

onOpenChange
(details: OpenChangeDetails) => void

Function called when the popup is opened

onPointerDownOutside
(event: PointerDownOutsideEvent) => void

Function called when the pointer is pressed down outside the component

onValueChange
(details: ValueChangeDetails<T>) => void

Function called when a new item is selected

open
boolean

Whether the combobox is open

openOnChangetrue
boolean | ((details: InputValueChangeDetails) => boolean)

Whether to show the combobox when the input value changes

openOnClickfalse
boolean

Whether to open the combobox popup on initial click on the input

openOnKeyPresstrue
boolean

Whether to open the combobox on arrow key press

placeholder
string

The placeholder text of the combobox's input

positioning
PositioningOptions

The positioning options to dynamically position the menu

present
boolean

Whether the node is present (controlled by the user)

readOnly
boolean

Whether the combobox is readonly. This puts the combobox in a "non-editable" mode but the user can still interact with it

required
boolean

Whether the combobox is required

scrollToIndexFn
(details: ScrollToIndexDetails) => void

Function 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
IntlTranslations

Specifies the localized strings that identifies the accessibility elements and their states

unmountOnExitfalse
boolean

Whether to unmount on exit.

value
string[]

The keys of the selected items

Data AttributeValue
[data-scope]combobox
[data-part]root
[data-invalid]Present when invalid
[data-readonly]Present when read-only

ClearTrigger

PropDefaultType
asChild
(props: ParentProps<'button'>) => Element

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
Data AttributeValue
[data-scope]combobox
[data-part]clear-trigger
[data-invalid]Present when invalid

Content

PropDefaultType
asChild
(props: ParentProps<'div'>) => Element

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
Data AttributeValue
[data-scope]combobox
[data-part]content
[data-state]"open" | "closed"
[data-placement]The placement of the content

Control

PropDefaultType
asChild
(props: ParentProps<'div'>) => Element

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
Data AttributeValue
[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

PropDefaultType
asChild
(props: ParentProps<'input'>) => Element

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
Data AttributeValue
[data-scope]combobox
[data-part]input
[data-invalid]Present when invalid
[data-state]"open" | "closed"

ItemGroupLabel

PropDefaultType
asChild
(props: ParentProps<'div'>) => Element

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

ItemGroup

PropDefaultType
asChild
(props: ParentProps<'div'>) => Element

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

ItemIndicator

PropDefaultType
asChild
(props: ParentProps<'div'>) => Element

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
Data AttributeValue
[data-scope]combobox
[data-part]item-indicator
[data-state]"checked" | "unchecked"

Item

PropDefaultType
asChild
(props: ParentProps<'div'>) => Element

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
item
any

The item to render

persistFocus
boolean

Whether hovering outside should clear the highlighted state

Data AttributeValue
[data-scope]combobox
[data-part]item
[data-highlighted]Present when highlighted
[data-state]"checked" | "unchecked"
[data-disabled]Present when disabled
[data-value]The value of the item

ItemText

PropDefaultType
asChild
(props: ParentProps<'span'>) => Element

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
Data AttributeValue
[data-scope]combobox
[data-part]item-text
[data-state]"checked" | "unchecked"
[data-disabled]Present when disabled
[data-highlighted]Present when highlighted

Label

PropDefaultType
asChild
(props: ParentProps<'label'>) => Element

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
Data AttributeValue
[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

PropDefaultType
asChild
(props: ParentProps<'div'>) => Element

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

Positioner

PropDefaultType
asChild
(props: ParentProps<'div'>) => Element

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

RootProvider

PropDefaultType
value
UseComboboxReturn<T>

asChild
(props: ParentProps<'div'>) => Element

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
immediate
boolean

Whether to synchronize the present change immediately or defer it to the next frame

lazyMountfalse
boolean

Whether to enable lazy mounting

onExitComplete
() => void

Function called when the animation ends in the closed state

present
boolean

Whether the node is present (controlled by the user)

unmountOnExitfalse
boolean

Whether to unmount on exit.

Trigger

PropDefaultType
asChild
(props: ParentProps<'button'>) => Element

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
focusable
boolean

Whether the trigger is focusable

Data AttributeValue
[data-scope]combobox
[data-part]trigger
[data-state]"open" | "closed"
[data-invalid]Present when invalid
[data-focusable]
[data-readonly]Present when read-only
[data-disabled]Present when disabled

Accessibility

Complies with the Combobox WAI-ARIA design pattern.

Keyboard Support

KeyDescription
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