Combobox

An input field with an attached dropdown that allows users to search and select from a list of options.

Anatomy

Import and assemble the component:

1import { Combobox } from "@raystack/apsara";
2
3<Combobox>
4 <Combobox.Label />
5 <Combobox.Input />
6 <Combobox.Clear />
7 <Combobox.Content>
8 <Combobox.Empty />
9 <Combobox.Status />
10 <Combobox.Group>
11 <Combobox.GroupLabel />
12 <Combobox.Item />
13 </Combobox.Group>
14 <Combobox.Separator />
15 </Combobox.Content>
16</Combobox>

Usage

A combobox filters its list as the user types. The props below cover what the list holds, how many items can be picked, and who owns the value.

Basic

A simple combobox with search filtering built in. Type to filter options.

1<Combobox>
2 <Combobox.Input placeholder="Enter a fruit" />
3 <Combobox.Content>
4 <Combobox.Item>Apple</Combobox.Item>
5 <Combobox.Item>Banana</Combobox.Item>
6 <Combobox.Item>Grape</Combobox.Item>
7 <Combobox.Item>Orange</Combobox.Item>
8 </Combobox.Content>
9</Combobox>

With icons

You can pass the leadingIcon prop to Combobox.Item to display icons before item text.

1<Combobox>
2 <Combobox.Input placeholder="Select a fruit" width={240} />
3 <Combobox.Content>
4 <Combobox.Item value="apple" leadingIcon={<Info size={16} />}>
5 Apple
6 </Combobox.Item>
7 <Combobox.Item value="banana" leadingIcon={<X size={16} />}>
8 Banana
9 </Combobox.Item>
10 <Combobox.Item value="grape" leadingIcon={<Home size={16} />}>
11 Grape
12 </Combobox.Item>
13 <Combobox.Item value="orange" leadingIcon={<Laugh size={16} />}>
14 Orange

With Field

Wrap the Combobox with Field to add a label, description, and error handling.

1<Field label="Favorite Fruit" description="Choose your favorite fruit">
2 <Combobox>
3 <Combobox.Input placeholder="Select a fruit" width={240} />
4 <Combobox.Content>
5 <Combobox.Item value="apple">Apple</Combobox.Item>
6 <Combobox.Item value="banana">Banana</Combobox.Item>
7 <Combobox.Item value="blueberry">Blueberry</Combobox.Item>
8 <Combobox.Item value="grapes">Grapes</Combobox.Item>
9 </Combobox.Content>
10 </Combobox>
11</Field>

Groups and separators

Organize items into groups with Combobox.GroupLabel and separators. Groups, group labels, and separators are hidden while the user is searching.

1<Combobox>
2 <Combobox.Input placeholder="Search items" width={240} />
3 <Combobox.Content>
4 <Combobox.Group>
5 <Combobox.GroupLabel>Fruits</Combobox.GroupLabel>
6 <Combobox.Item value="apple">Apple</Combobox.Item>
7 <Combobox.Item value="banana">Banana</Combobox.Item>
8 </Combobox.Group>
9 <Combobox.Separator />
10 <Combobox.Group>
11 <Combobox.GroupLabel>Vegetables</Combobox.GroupLabel>
12 <Combobox.Item value="carrot">Carrot</Combobox.Item>
13 <Combobox.Item value="broccoli">Broccoli</Combobox.Item>
14 </Combobox.Group>

Multiple selection

Pass the multiple prop to enable multi-select. Selected values appear as chips in the input. Items display checkboxes in multiple mode.

The input shows the first two chips and a "+N" count for the rest. Press Backspace in an empty input to remove the last value. Press Left Arrow at the start of the input to move focus to the chips. On a focused chip, press Backspace or Delete to remove it.

1<Combobox multiple>
2 <Combobox.Input placeholder="Select fruits" width={300} />
3 <Combobox.Content>
4 <Combobox.Item>Apple</Combobox.Item>
5 <Combobox.Item>Banana</Combobox.Item>
6 <Combobox.Item>Grape</Combobox.Item>
7 <Combobox.Item>Orange</Combobox.Item>
8 <Combobox.Item>Mango</Combobox.Item>
9 <Combobox.Item>Pineapple</Combobox.Item>
10 <Combobox.Item>Strawberry</Combobox.Item>
11 <Combobox.Item>Watermelon</Combobox.Item>
12 <Combobox.Item>Kiwi</Combobox.Item>
13 <Combobox.Item>Lemon</Combobox.Item>
14 <Combobox.Item>Lime</Combobox.Item>

Label and clear button

Combobox.Label renders a visible label linked to the input. Combobox.Clear renders a button that clears the value. It shows only when there is a value or input text. Place both anywhere inside Combobox.

1<Combobox multiple>
2 <Flex direction="column" gap={2}>
3 <Combobox.Label>Fruits</Combobox.Label>
4 <Flex align="center" gap={2}>
5 <Combobox.Input placeholder="Select fruits" width={300} />
6 <Combobox.Clear />
7 </Flex>
8 </Flex>
9 <Combobox.Content>
10 <Combobox.Item>Apple</Combobox.Item>
11 <Combobox.Item>Banana</Combobox.Item>
12 <Combobox.Item>Grape</Combobox.Item>
13 <Combobox.Item>Orange</Combobox.Item>
14 </Combobox.Content>

Empty state

Combobox.Content shows "No results" when no item matches the input. To change the text, add Combobox.Empty as a direct child of Combobox.Content.

1<Combobox>
2 <Combobox.Input placeholder="Type 'xyz'" width={240} />
3 <Combobox.Content>
4 <Combobox.Empty>No fruit matches your search</Combobox.Empty>
5 <Combobox.Item>Apple</Combobox.Item>
6 <Combobox.Item>Banana</Combobox.Item>
7 <Combobox.Item>Grape</Combobox.Item>
8 </Combobox.Content>
9</Combobox>

Controlled

Use value and onValueChange for controlled behavior.

1(function ControlledDemo() {
2 const [value, setValue] = React.useState("");
3 const [inputValue, setInputValue] = React.useState("");
4
5 return (
6 <Flex direction="column" gap={5}>
7 <Text>Selected: {value || "None"}</Text>
8 <Combobox
9 value={value}
10 onValueChange={setValue}
11 inputValue={inputValue}
12 onInputValueChange={setInputValue}
13 >
14 <Combobox.Input placeholder="Enter a fruit" />

Using IDs as values

When your app stores IDs instead of item objects, wrap the data with Combobox.createItems. getValue returns the value that value and onValueChange use. getLabel returns the text shown in the input and used for filtering. Pass a function as the child of Combobox.Content to render each item that matches the input.

Create the collection at module scope for static data. For data that changes, wrap it in React.useMemo keyed by the data.

1(function CreateItemsDemo() {
2 const users = [
3 { id: "u1", name: "Jane Doe" },
4 { id: "u2", name: "John Smith" },
5 { id: "u3", name: "Ada Lovelace" },
6 ];
7 const items = React.useMemo(
8 () =>
9 Combobox.createItems(users, {
10 getValue: (user) => user.id,
11 getLabel: (user) => user.name,
12 }),
13 []
14 );

API Reference

Root and input first, then the parts that make up the popup list.

Root Props

The Combobox component is composed of several parts, each with their own props.

The root element is the parent component that manages the combobox state including open/close, input value, and selection.

Prop

Type

Input Props

The input field that triggers the combobox dropdown and allows users to type and filter options.

Prop

Type

Content Props

The dropdown container that holds the combobox items.

Prop

Type

Item Props

Individual selectable options within the combobox. In single mode, selecting an item closes the dropdown. In multiple mode, items show checkboxes and the dropdown remains open.

When no value prop is provided, the text content of children is used as the value.

Prop

Type

Label Props

A visible label for the input. It renders a <label> whose htmlFor is the input id. Inside a Field, use the Field label instead.

Prop

Type

Clear Props

A button that clears the value and the input text. It renders IconButton and shows only when there is something to clear.

Prop

Type

Empty Props

The text shown when no item matches the input. Combobox.Content renders one with "No results" by default. Add Combobox.Empty as a direct child of Combobox.Content to change the text. Pass null as children to show nothing.

Prop

Type

Status Props

A visually hidden live region. Screen readers announce its text when it changes. Combobox.Content renders one by default that announces the number of matching items, for example "3 results". Add Combobox.Status as a direct child of Combobox.Content to change the text, for example to announce loading.

Prop

Type

Group Props

A way to group related combobox items together.

Prop

Type

GroupLabel Props

Renders a label in a combobox group. Wrap it in Combobox.Group.

Prop

Type

Separator Props

Visual divider between combobox items or groups.

Prop

Type

Slots

Every rendered part carries a stable data-slot attribute for styling and testing:

SlotElement
combobox-labelThe label for the input
combobox-inputThe text input that opens the popup
combobox-chipsThe container for chips and the input in multiple mode
combobox-chipA selected value in multiple mode
combobox-chip-removeThe button that removes a chip
combobox-chip-overflowThe "+N" count of chips that are not shown
combobox-clearThe button that clears the value
combobox-positionerWrapper that positions the popup
combobox-contentThe popup container
combobox-statusThe hidden live region that announces the number of results
combobox-emptyThe text shown when no item matches
combobox-listThe scrollable list of items
combobox-groupA group of related items
combobox-group-labelThe label for a group
combobox-separatorThe divider between items or groups
combobox-itemA selectable option row
combobox-item-textThe text label inside an item (when its children is a string)
combobox-item-iconThe leading icon inside an item (when leadingIcon is set)

Accessibility

  • Follows the WAI-ARIA Combobox pattern via Base UI Combobox: the input is a role="combobox" with aria-expanded and aria-controls, the popup list is a listbox, and each item is an option with aria-selected.
  • Arrow keys move the highlight through visible options, Enter selects the highlighted option, and Escape closes the popup, and focus stays in the input the whole time, so typing to filter never loses the user's place.
  • In multiple mode, each item renders a checkbox that mirrors its selected state, and selected values appear in the input as removable chips.
  • The chips use Base UI's Combobox.Chips, which has role="toolbar". Arrow keys move between chips, and Backspace or Delete removes the focused chip.
  • Combobox.Empty and Combobox.Status are polite live regions. Screen readers announce "No results" and the number of matching items.
  • Group labels use Base UI's Combobox.GroupLabel, which links the label to its group via aria-labelledby, so wrap Combobox.GroupLabel in Combobox.Group.
  • Wrap the Combobox with Field to associate a visible label, description, and error message with the input.