import {Layout} from '../../src/Layout'; export default Layout;
import docs from 'docs:react-aria-components'; import {ComboBox as VanillaComboBox, ComboBoxItem} from 'vanilla-starter/ComboBox'; import vanillaDocs from 'docs:vanilla-starter/ComboBox'; import '../../tailwind/tailwind.css'; import Anatomy from 'react-aria-components/docs/ComboBoxAnatomy.svg';
export const tags = ['autocomplete', 'search', 'typeahead', 'input'];
{docs.exports.ComboBox.description}
```tsx render docs={vanillaDocs.exports.ComboBox} links={vanillaDocs.links} props={['label', 'isDisabled']} initialProps={{label: 'Favorite Animal'}} type="vanilla" files={["starters/docs/src/ComboBox.tsx", "starters/docs/src/ComboBox.css"]} "use client"; import {ComboBox, ComboBoxItem} from 'vanilla-starter/ComboBox';<ComboBox/* PROPS */> Aardvark Cat Dog Kangaroo Panda Snake
```tsx render docs={vanillaDocs.exports.ComboBox} links={vanillaDocs.links} props={['label', 'isDisabled']} initialProps={{label: 'Favorite Animal'}} type="tailwind" files={["starters/tailwind/src/ComboBox.tsx"]}
"use client";
import {ComboBox, ComboBoxItem} from 'tailwind-starter/ComboBox';
<ComboBox/* PROPS */>
<ComboBoxItem>Aardvark</ComboBoxItem>
<ComboBoxItem>Cat</ComboBoxItem>
<ComboBoxItem>Dog</ComboBoxItem>
<ComboBoxItem>Kangaroo</ComboBoxItem>
<ComboBoxItem>Panda</ComboBoxItem>
<ComboBoxItem>Snake</ComboBoxItem>
</ComboBox>
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.
"use client";
import {ComboBox} from 'vanilla-starter/ComboBox';
import {ListBoxSection, ListBoxItem, Collection, Header} from 'react-aria-components';
function Example() {
/*- begin collapse -*/
let options = [
{name: 'Fruit', children: [
{name: 'Apple'},
{name: 'Banana'},
{name: 'Orange'},
{name: 'Honeydew'},
{name: 'Grapes'},
{name: 'Watermelon'},
{name: 'Cantaloupe'},
{name: 'Pear'}
]},
{name: 'Vegetable', children: [
{name: 'Cabbage'},
{name: 'Broccoli'},
{name: 'Carrots'},
{name: 'Lettuce'},
{name: 'Spinach'},
{name: 'Bok Choy'},
{name: 'Cauliflower'},
{name: 'Potatoes'}
]}
];
/*- end collapse -*/
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>
);
}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.
"use client";
import type {Key} from 'react-aria-components';
import {ComboBox, ComboBoxItem} from 'vanilla-starter/ComboBox';
import {useState} from 'react';
function Example() {
let [animal, setAnimal] = useState<Key>("bison");
return (
<div>
<ComboBox
label="Pick an animal"
/*- begin highlight -*/
selectedKey={animal}
onSelectionChange={setAnimal}>
{/*- end highlight -*/}
<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>
);
}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.
"use client";
import type {Key} from 'react-aria-components';
import {ComboBox, ComboBoxItem} from 'vanilla-starter/ComboBox';
import {useState} from 'react';
function Example(props) {
let [value, setValue] = useState<Key>('Kangaroo');
return (
<div>
<ComboBox
{...props}
label="Favorite Animal"
/*- begin highlight -*/
/* PROPS */
inputValue={value}
onInputChange={setValue}>
{/*- end highlight -*/}
<ComboBoxItem id="koala">Koala</ComboBoxItem>
<ComboBoxItem id="kangaroo">Kangaroo</ComboBoxItem>
<ComboBoxItem id="platypus">Platypus</ComboBoxItem>
<ComboBoxItem id="eagle">Bald Eagle</ComboBoxItem>
<ComboBoxItem id="bison">Bison</ComboBoxItem>
<ComboBoxItem id="skunk">Skunk</ComboBoxItem>
</ComboBox>
<p>Current input value: {value}</p>
</div>
);
}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.
"use client";
import type {Key} from 'react-aria-components';
import {ComboBox, ComboBoxItem} from 'vanilla-starter/ComboBox';
import {useState} from 'react';
function ControlledComboBox() {
/*- begin collapse -*/
let options = [
{id: 1, name: 'Aerospace'},
{id: 2, name: 'Mechanical'},
{id: 3, name: 'Civil'},
{id: 4, name: 'Biomedical'},
{id: 5, name: 'Nuclear'},
{id: 6, name: 'Industrial'},
{id: 7, name: 'Chemical'},
{id: 8, name: 'Agricultural'},
{id: 9, name: 'Electrical'}
];
/*- end collapse -*/
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"
/*- begin highlight -*/
defaultItems={options}
selectedKey={fieldState.selectedKey}
inputValue={fieldState.inputValue}
onSelectionChange={onSelectionChange}
onInputChange={onInputChange}>
{/*- end highlight -*/}
{item => <ComboBoxItem>{item.name}</ComboBoxItem>}
</ComboBox>
<pre style={{fontSize: 12}}>
Current selected major id: {fieldState.selectedKey}{'\n'}
Current input text: {fieldState.inputValue}
</pre>
</div>
);
}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.
"use client";
import {ComboBox, ComboBoxItem} from 'vanilla-starter/ComboBox';
import {useState} from 'react';
function Example() {
let [inputValue, setInputValue] = useState('');
return (
<ComboBox
label="Favorite Animal"
allowsEmptyCollection
inputValue={inputValue}
onInputChange={setInputValue}>
{/*- begin highlight -*/}
{inputValue.length > 0 && (
<ComboBoxItem onAction={() => alert('Creating ' + inputValue)}>
{`Create "${inputValue}"`}
</ComboBoxItem>
)}
{/*- end highlight -*/}
<ComboBoxItem>Aardvark</ComboBoxItem>
<ComboBoxItem>Cat</ComboBoxItem>
<ComboBoxItem>Dog</ComboBoxItem>
<ComboBoxItem>Kangaroo</ComboBoxItem>
<ComboBoxItem>Panda</ComboBoxItem>
<ComboBoxItem>Snake</ComboBoxItem>
</ComboBox>
);
}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.
"use client";
import {ComboBox, ComboBoxItem} from 'vanilla-starter/ComboBox';
import {Button} from 'vanilla-starter/Button';
import {Form} from 'react-aria-components';
<Form>
<ComboBox
label="Animal"
/*- begin highlight -*/
name="animal"
isRequired
/*- end highlight -*/
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>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.
"use client";
import {ComboBox, ComboBoxItem} from 'vanilla-starter/ComboBox';
<ComboBox/* PROPS */>
<ComboBoxItem id="red panda">Red Panda</ComboBoxItem>
<ComboBoxItem id="cat">Cat</ComboBoxItem>
<ComboBoxItem id="dog">Dog</ComboBoxItem>
<ComboBoxItem id="aardvark">Aardvark</ComboBoxItem>
<ComboBoxItem id="kangaroo">Kangaroo</ComboBoxItem>
<ComboBoxItem id="snake">Snake</ComboBoxItem>
</ComboBox><ComboBox>
<Label />
<Input />
<Button />
<Text slot="description" />
<FieldError />
<Popover>
<ListBox />
</Popover>
</ComboBox>