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
children
ReactNode & CollectionChildren<object>
The contents of the collection.containerRef?
RefObject<HTMLElement>
The ref of the element to append the overlay to.helperText?
ReactNode
Helper text to append to the form control input element.helperTextProps?
HTMLAttributes<HTMLElement>
Props passed to the helper text.label?
ReactNode
Label of the input elementlabelProps?
HTMLAttributes<HTMLElement>
Props passed to the label.maxHeight?
number
The maxHeight specified for the overlay element.
By default, it will take all space up to the current viewport height.offset?
number
The additional offset applied along the main axis between the element and its
anchor element.Defaults to 4
placement?
Placement
The placement of the element with respect to its anchor element.Defaults to 'bottom'
shouldFlip?
boolean
Whether the element should flip its orientation (e.g. top to bottom or left to right) when
there is insufficient room for it to render completely.Defaults to true
size?
"small" | "medium"
The size of the comboboxDefaults to 'medium'
startIcon?
ReactElement<any, string | JSXElementConstructor<any>>
Icon displayed at the start of the combobox.variant?
"autocomplete" | "dropdown"
Combobox variantloading?
boolean
Specifies if the component is in a loading stateloadingText?
string
Specifies the loading state content for the combobox. If not provided
no text will be displayed in the loading statenoResultsChildren?
ReactElement<any, string | JSXElementConstructor<any>> | ReactElement<any, string | JSXElementConstructor<any>>[]
Specifies the no results ui elements for the comboboxas?
NonNullable<T>
css?
CSS
Theme aware style object.ComboboxItem Props
as?The root element to be rendered
as?
"div"
css?
CSS
Theme aware style object.startIcon?
ReactElement<any, string | JSXElementConstructor<any>>
Icon added before the item text.ComboboxSection Props
as?The root element to be rendered
as?
"div"
children
ReactNode & (ItemElement<object> | ItemElement<object>[] | ItemRenderer<object>)
Static child items or a function to render children.css?
CSS
Theme aware style object.