Skip to main content
The Combobox component provides a searchable dropdown interface that allows users to filter and select from a list of options. It supports both single and multiple selection modes.

Basic usage

import { Combobox } from '@raystack/apsara';

function App() {
  return (
    <Combobox>
      <Combobox.Input placeholder="Search..." />
      <Combobox.Content>
        <Combobox.Item value="react">React</Combobox.Item>
        <Combobox.Item value="vue">Vue</Combobox.Item>
        <Combobox.Item value="angular">Angular</Combobox.Item>
      </Combobox.Content>
    </Combobox>
  );
}

Props

Combobox (Root)

value
Value | Value[] | null
The controlled value of the combobox. Use single value for single selection, array for multiple.
defaultValue
Value | Value[] | null
The default value for uncontrolled usage.
onValueChange
(value: Value | Value[] | null) => void
Callback fired when the selected value changes.
onInputValueChange
(inputValue: string) => void
Callback fired when the input value changes.
multiple
boolean
default:"false"
Whether multiple selections are allowed.
items
Value[]
Array of items for the combobox. Used for controlled item filtering.
open
boolean
Controls the open state of the combobox dropdown.
onOpenChange
(open: boolean) => void
Callback fired when the open state changes.

Combobox.Input

Inherits all props from InputField component except trailingIcon, suffix, chips, and maxChipsVisible.
label
string
The label text displayed above the input.
placeholder
string
Placeholder text for the input.
disabled
boolean
Whether the input is disabled.
error
string
Error message to display.
helperText
string
Helper text displayed below the input.
size
'small' | 'large'
The size of the input.

Combobox.Item

value
string
required
The value of the combobox item.
disabled
boolean
Whether the item is disabled.

Single selection

function SingleCombobox() {
  const [value, setValue] = useState(null);

  return (
    <Combobox value={value} onValueChange={setValue}>
      <Combobox.Input label="Framework" placeholder="Select a framework" />
      <Combobox.Content>
        <Combobox.Item value="react">React</Combobox.Item>
        <Combobox.Item value="vue">Vue</Combobox.Item>
        <Combobox.Item value="angular">Angular</Combobox.Item>
        <Combobox.Item value="svelte">Svelte</Combobox.Item>
      </Combobox.Content>
    </Combobox>
  );
}

Multiple selection

function MultiCombobox() {
  const [values, setValues] = useState([]);

  return (
    <Combobox multiple value={values} onValueChange={setValues}>
      <Combobox.Input label="Technologies" placeholder="Select technologies" />
      <Combobox.Content>
        <Combobox.Item value="react">React</Combobox.Item>
        <Combobox.Item value="typescript">TypeScript</Combobox.Item>
        <Combobox.Item value="nodejs">Node.js</Combobox.Item>
        <Combobox.Item value="graphql">GraphQL</Combobox.Item>
      </Combobox.Content>
    </Combobox>
  );
}

With groups and labels

<Combobox>
  <Combobox.Input placeholder="Select a tool" />
  <Combobox.Content>
    <Combobox.Group>
      <Combobox.Label>Frontend</Combobox.Label>
      <Combobox.Item value="react">React</Combobox.Item>
      <Combobox.Item value="vue">Vue</Combobox.Item>
    </Combobox.Group>
    <Combobox.Separator />
    <Combobox.Group>
      <Combobox.Label>Backend</Combobox.Label>
      <Combobox.Item value="nodejs">Node.js</Combobox.Item>
      <Combobox.Item value="python">Python</Combobox.Item>
    </Combobox.Group>
  </Combobox.Content>
</Combobox>

With input value tracking

function SearchableCombobox() {
  const [value, setValue] = useState(null);
  const [inputValue, setInputValue] = useState('');

  return (
    <div>
      <Combobox
        value={value}
        onValueChange={setValue}
        onInputValueChange={setInputValue}
      >
        <Combobox.Input placeholder="Search items" />
        <Combobox.Content>
          <Combobox.Item value="apple">Apple</Combobox.Item>
          <Combobox.Item value="banana">Banana</Combobox.Item>
          <Combobox.Item value="orange">Orange</Combobox.Item>
        </Combobox.Content>
      </Combobox>
      <p>Searching for: {inputValue}</p>
    </div>
  );
}

With custom filtering

function FilteredCombobox() {
  const [value, setValue] = useState(null);
  const [inputValue, setInputValue] = useState('');
  
  const allItems = [
    { value: 'apple', label: 'Apple' },
    { value: 'banana', label: 'Banana' },
    { value: 'orange', label: 'Orange' },
    { value: 'grape', label: 'Grape' }
  ];
  
  const filteredItems = allItems.filter(item =>
    item.label.toLowerCase().includes(inputValue.toLowerCase())
  );

  return (
    <Combobox
      value={value}
      onValueChange={setValue}
      onInputValueChange={setInputValue}
      items={filteredItems.map(i => i.value)}
    >
      <Combobox.Input placeholder="Filter items" />
      <Combobox.Content>
        {filteredItems.map(item => (
          <Combobox.Item key={item.value} value={item.value}>
            {item.label}
          </Combobox.Item>
        ))}
      </Combobox.Content>
    </Combobox>
  );
}

With validation

<Combobox>
  <Combobox.Input
    label="Country"
    error="Please select a country"
    placeholder="Select your country"
  />
  <Combobox.Content>
    <Combobox.Item value="us">United States</Combobox.Item>
    <Combobox.Item value="uk">United Kingdom</Combobox.Item>
    <Combobox.Item value="ca">Canada</Combobox.Item>
  </Combobox.Content>
</Combobox>

Multiple selection with chips

When using multiple selection mode, selected items are automatically displayed as removable chips in the input field.
<Combobox multiple value={['react', 'typescript']} onValueChange={setValues}>
  <Combobox.Input label="Skills" placeholder="Add skills" />
  <Combobox.Content>
    <Combobox.Item value="react">React</Combobox.Item>
    <Combobox.Item value="typescript">TypeScript</Combobox.Item>
    <Combobox.Item value="nodejs">Node.js</Combobox.Item>
  </Combobox.Content>
</Combobox>

Accessibility

  • Built on Base UI Combobox primitive with full accessibility support.
  • Supports keyboard navigation with arrow keys, Enter to select, and Escape to close.
  • Proper ARIA attributes are automatically applied.
  • Screen readers announce the number of available options and selected values.
  • In multiple selection mode, chips can be removed using keyboard navigation.