ComboBox
A combo box combines a text input with a listbox, allowing users to filter a list of options to items matching a query.
Content
ComboBox
reuses the ListBox
component, following the Collection Components API. It supports ListBox features such as static and dynamic collections, sections, disabled items, links, text slots, asynchronous loading, etc. See the ListBox docs for more details.
The following example shows a dynamic collection of items, grouped into sections.
import {ComboBox} from './ComboBox';
import {ListBoxSection, ListBoxItem, Collection, Header} from 'react-aria-components';
function Example() {
return (
<ComboBox label="Preferred fruit or vegetable" items={options}>
{section => (
<ListBoxSection id={section.name}>
<Header>{section.name}</Header>
<Collection items={section.children}>
{item => <ListBoxItem id={item.name}>{item.name}</ListBoxItem>}
</Collection>
</ListBoxSection>
)}
</ComboBox>
);
}
Selection
Use the defaultSelectedKey
or selectedKey
prop to set the selected item. The selected key corresponds to the id
prop of an item. Items can be disabled with the isDisabled
prop. See the selection guide for more details.
Current selection: bison
import type {Key} from 'react-aria-components';
import {ComboBox, ComboBoxItem} from './ComboBox';
import {useState} from 'react';
function Example() {
let [animal, setAnimal] = useState<Key>("bison");
return (
<div>
<ComboBox
label="Pick an animal"
selectedKey={animal}
onSelectionChange={setAnimal}>
<ComboBoxItem id="koala">Koala</ComboBoxItem>
<ComboBoxItem id="kangaroo">Kangaroo</ComboBoxItem>
<ComboBoxItem id="platypus" isDisabled>Platypus</ComboBoxItem>
<ComboBoxItem id="eagle">Bald Eagle</ComboBoxItem>
<ComboBoxItem id="bison">Bison</ComboBoxItem>
<ComboBoxItem id="skunk">Skunk</ComboBoxItem>
</ComboBox>
<p>Current selection: {animal}</p>
</div>
);
}
Input value
Use the inputValue
or defaultInputValue
prop to set the value of the input field. By default, the value will be reverted to the selected item on blur. Set the allowsCustomValue
prop to enable entering values that are not in the list.
Current input value: Kangaroo
Fully controlled
Both inputValue
and selectedKey
can be controlled simultaneously. However, each interaction will only trigger either onInputChange
or onSelectionChange
, not both. When controlling both props, you must update both values accordingly.
Current selected major id: Current input text:
import type {Key} from 'react-aria-components';
import {ComboBox, ComboBoxItem} from './ComboBox';
import {useState} from 'react';
function ControlledComboBox() {
let [fieldState, setFieldState] = useState({
selectedKey: null,
inputValue: ''
});
let onSelectionChange = (id: Key) => {
// Update inputValue when selectedKey changes.
setFieldState({
inputValue: options.find(o => o.id === id)?.name ?? '',
selectedKey: id
});
};
let onInputChange = (value: string) => {
// Reset selectedKey to null if the input is cleared.
setFieldState(prevState => ({
inputValue: value,
selectedKey: value === '' ? null : prevState.selectedKey
}));
};
return (
<div>
<ComboBox
label="Pick a engineering major"
defaultItems={options}
selectedKey={fieldState.selectedKey}
inputValue={fieldState.inputValue}
onSelectionChange={onSelectionChange}
onInputChange={onInputChange}>
{item => <ComboBoxItem>{item.name}</ComboBoxItem>}
</ComboBox>
<pre style={{fontSize: 12}}>
Current selected major id: {fieldState.selectedKey}{'\n'}
Current input text: {fieldState.inputValue}
</pre>
</div>
);
}
Item actions
Use the onAction
prop on a <ListBoxItem>
to perform a custom action when the item is pressed. This example adds a "Create" action for the current input value.
import {ComboBox, ComboBoxItem} from './ComboBox';
import {useState} from 'react';
function Example() {
let [inputValue, setInputValue] = useState('');
return (
<ComboBox
label="Favorite Animal"
allowsEmptyCollection
inputValue={inputValue}
onInputChange={setInputValue}>
{inputValue.length > 0 && (
<ComboBoxItem onAction={() => alert('Creating ' + inputValue)}>
{`Create "${inputValue}"`}
</ComboBoxItem>
)}
<ComboBoxItem>Aardvark</ComboBoxItem>
<ComboBoxItem>Cat</ComboBoxItem>
<ComboBoxItem>Dog</ComboBoxItem>
<ComboBoxItem>Kangaroo</ComboBoxItem>
<ComboBoxItem>Panda</ComboBoxItem>
<ComboBoxItem>Snake</ComboBoxItem>
</ComboBox>
);
}
Forms
Use the name
prop to submit the id
of the selected item to the server. Set the isRequired
prop to validate that the user selects a value, or implement custom client or server-side validation. See the Forms guide to learn more.
import {ComboBox, ComboBoxItem} from './ComboBox';
import {Button} from './Button';
import {Form} from 'react-aria-components';
<Form>
<ComboBox
label="Animal"
name="animal"
isRequired
description="Please select an animal.">
<ComboBoxItem id="aardvark">Aardvark</ComboBoxItem>
<ComboBoxItem id="cat">Cat</ComboBoxItem>
<ComboBoxItem id="dog">Dog</ComboBoxItem>
<ComboBoxItem id="kangaroo">Kangaroo</ComboBoxItem>
<ComboBoxItem id="panda">Panda</ComboBoxItem>
<ComboBoxItem id="snake">Snake</ComboBoxItem>
</ComboBox>
<Button type="submit">Submit</Button>
</Form>
Popover
Use the menuTrigger
prop to control when the popover opens:
input
(default): popover opens when the user edits the input text.focus
: popover opens when the user focuses the input.manual
: popover only opens when the user presses the trigger button or uses the arrow keys.
Use allowsEmptyCollection
to keep the popover open when there are no items available in the list.