Combobox
An autocomplete input that allows a user to filter a list of selectable options.
<Combobox aria-label="Country Select"> <ComboboxItem>United States</ComboboxItem> <ComboboxItem>Canada</ComboboxItem> <ComboboxItem>Mexico</ComboboxItem> </Combobox>
Usage
Selection
Setting a selected option can be done by using the defaultSelectedKey
or selectedKey
prop
function Selection() { const options = [ { id: 1, name: 'United States' }, { id: 2, name: 'Canada' }, { id: 3, name: 'Mexico' }, { id: 4, name: 'United Kingdom' }, { id: 5, name: 'France' }, { id: 6, name: 'China' }, { id: 7, name: 'India' }, { id: 8, name: 'Turkey' }, ]; const [selected, setSelected] = React.useState('Turkey'); return ( <Combobox aria-label="Country Select" selectedKey={selected} onSelectionChange={setSelected}> {options.map((item) => ( <ComboboxItem key={item.name}>{item.name}</ComboboxItem> ))} </Combobox> ); }
Sections
Group items within a dropdown using a section.
<Combobox aria-label="Country Select"> <ComboboxSection title="North America"> <ComboboxItem>United States</ComboboxItem> <ComboboxItem>Canada</ComboboxItem> <ComboboxItem>Mexico</ComboboxItem> </ComboboxSection> <ComboboxSection title="Europe"> <ComboboxItem>United Kingdom</ComboboxItem> <ComboboxItem>France</ComboboxItem> </ComboboxSection> <ComboboxSection title="Asia"> <ComboboxItem>China</ComboboxItem> <ComboboxItem>India</ComboboxItem> </ComboboxSection> </Combobox>
Variant
Combobox has two variant, dropdown and autocomplete. The main difference between the two is that the dropdown variant renders a dropdown button next to the input.
<Flex gap="small"> <Combobox variant="dropdown" helperText="Dropdown variant"> <ComboboxItem>United States</ComboboxItem> <ComboboxItem>Canada</ComboboxItem> <ComboboxItem>Mexico</ComboboxItem> </Combobox> <Combobox variant="autocomplete" helperText="Autocomplete variant"> <ComboboxItem>United States</ComboboxItem> <ComboboxItem>Canada</ComboboxItem> <ComboboxItem>Mexico</ComboboxItem> </Combobox> </div>
Loading state
Combobox gives you the control over what text should be rendered in a loading state
<Combobox loading loadingText="Loading state text goes here..." helperText="Click dropdown arrow to view loading state..."> <ComboboxItem key="ardvark">Ardvark</ComboboxItem> <ComboboxItem key="kangaroo">Kangaroo</ComboboxItem> <ComboboxItem key="snake">Snake</ComboboxItem> </Combobox>
No results state
<Combobox helperText="Start typing 'test' to see no results state..." noResultsChildren={ <Flex justify="center"> <Typography variant="caption" css={{ color: '$text-secondary' }}> No results state goes here... </Typography> </Flex> } > <ComboboxItem key="ardvark">Ardvark</ComboboxItem> </Combobox>
Async
Items can be loaded asynchronously use the useAsyncData
hook. It also supports infinite scrolling
to load more data on demand as the user scrolls, via the onLoadMore prop.
function Async() { const list = useAsyncList({ async load({ signal, filterText }) { const res = await fetch(`https://restcountries.com/v3.1/name/${filterText}`, { signal, }); if (res.status !== 200) return { items: [] }; const items = await res.json() return { items: items.map((x) => ({ value: x.name.common, })), }; }, }); const handleInputChanged = React.useCallback( (value) => list.setFilterText(value), [list], ); return ( <Combobox aria-label="test" inputValue={list.filterText} items={list.items} loading={list.isLoading} loadingText="Searching an free list of countries..." noResultsChildren={<Flex justify="center"><Typography variant="caption">😭 No results found</Typography></Flex>} onInputChange={handleInputChanged} variant="autocomplete" placeholder="Start typing to search for a country..." > {(item) => ( <ComboboxItem key={item.value}>{item.value}</ComboboxItem> )} </Combobox> ); }
Label
Attach a label to the combobox using the label
prop.
<Combobox label="Country"> <ComboboxItem>United States</ComboboxItem> <ComboboxItem>Canada</ComboboxItem> <ComboboxItem>Mexico</ComboboxItem> </Combobox>
HelperText
Add additional context as well as display error messages with the helperText
prop.
<Combobox label="Country" helperText="Please select a country"> <ComboboxItem>United States</ComboboxItem> <ComboboxItem>Canada</ComboboxItem> <ComboboxItem>Mexico</ComboboxItem> </Combobox>
Small
A small combobox is used when vertical spacing is limited.
<Combobox aria-label="Country Select" size="small"> <ComboboxItem>United States</ComboboxItem> <ComboboxItem>Canada</ComboboxItem> <ComboboxItem>Mexico</ComboboxItem> </Combobox>
Start Icon
Include an icon before the input text.
<Combobox aria-label="status" startIcon={<Search />}> <ComboboxItem>United States</ComboboxItem> <ComboboxItem>Canada</ComboboxItem> <ComboboxItem>Mexico</ComboboxItem> </Combobox>
Item Icon
Include an icon before the item label on each item.
<Combobox aria-label="status"> <ComboboxItem startIcon={<Truck />}>Truck</ComboboxItem> <ComboboxItem startIcon={<Train />}>Train</ComboboxItem> <ComboboxItem startIcon={<Airplane />}>Airplane</ComboboxItem> <ComboboxItem startIcon={<Boat />}>Ship</ComboboxItem> </Combobox>
Controlled
A combobox's state can be fully controlled including both the text input and item selection.
function ControlledExample() { const data = [ { id: 1, name: 'United States' }, { id: 2, name: 'Canada' }, { id: 3, name: 'Mexico' }, { id: 4, name: 'United Kingdom' }, { id: 5, name: 'France' }, { id: 6, name: 'China' }, { id: 7, name: 'India' }, { id: 8, name: 'Turkey' }, ]; const list = useTreeData({ initialItems: data }); const [state, dispatch] = React.useReducer( (state, action) => { switch (action.type) { case 'INPUT_CHANGE': return { inputValue: action.payload, selectedId: action.payload === '' ? null : state.selectedId, }; case 'SELECTION_CHANGE': return { inputValue: action.payload ? list.getItem(action.payload).value.name : '', selectedKey: action.payload, }; default: throw new Error(); } }, { inputValue: '', selectedKey: null }, ); return ( <Combobox aria-label="status" defaultItems={list.items} inputValue={state.inputValue} onInputChange={(value) => dispatch({ type: 'INPUT_CHANGE', payload: value })} onSelectionChange={(key) => dispatch({ type: 'SELECTION_CHANGE', payload: key })} selectedKey={state.selectedKey} > {(item) => <ComboboxItem>{item.value.name}</ComboboxItem>} </Combobox> ); }
Disabled State
Set the isDisabled
prop to prevent a user from interacting with the combobox.
<Combobox aria-label="status" isDisabled> <SelectItem>United States</SelectItem> <SelectItem>Canada</SelectItem> <SelectItem>Mexico</SelectItem> </Combobox>
Disabled items
Set the disabledKeys
prop to disable certain items in the combobox list.
<Combobox aria-label="status" disabledKeys={['canada']}> <ComboboxItem key="united_states">United States</ComboboxItem> <ComboboxItem key="canada">Canada</ComboboxItem> <ComboboxItem key="mexico">Mexico</ComboboxItem> </Combobox>
Invalid State
Set the validationState
prop to invalid
to render the combobox in an invalid state.
<Combobox aria-label="status" helperText="A selection is required" validationState="invalid"> <ComboboxItem>United States</ComboboxItem> <ComboboxItem>Canada</ComboboxItem> <ComboboxItem>Mexico</ComboboxItem> </Combobox>
Props
Combobox Props
as?The root element to be rendered
ComboboxItem Props
as?The root element to be rendered
ComboboxSection Props
as?The root element to be rendered