Combobox
This component allows users to select from a list of options. It’s especially useful when there are many options to choose from.
import { ... } from '@ag.ds-next/react/combobox';
As the user enters text into the field, autocomplete offers suggestions, highlighting the one that best matches the text that has been entered. The list closes when an option is selected.
All Combobox components are controlled components which means consumers of these components need to manage the state of these components by using the value
and onChange
props.
() => { const [value, setValue] = React.useState(null); return ( <Combobox label="Select country" hint="Start typing to see results" value={value} onChange={setValue} options={COUNTRY_OPTIONS} /> ); };
Do
- use to help users select from a large list
- provide concise options
- create hint text to let the user know they can search or select
- use a pre-filled list so users can search or scroll
- consider whether the list of selections is complex enough to merit searching and filtering
- indicate whether input is optional.
Don’t
- use if the list of possible results is small – use Select instead
- leave the list open once an option is selected.
Combobox
Use the Combobox
component when users can choose a single item from a predefined list of options.
() => { const [value, setValue] = React.useState(null); return ( <Combobox label="Select country" hint="Start typing to see results" value={value} onChange={setValue} options={COUNTRY_OPTIONS} /> ); };
ComboboxAsync
Use the ComboboxAsync
component when users can choose a single item from a list of options that needs to be fetched over the network.
() => { const [value, setValue] = React.useState(null); return ( <ComboboxAsync label="Select country" hint="Start typing to see results" value={value} onChange={setValue} loadOptions={async function loadOptions(inputValue) { // Simulate a slow network call await new Promise((resolve) => setTimeout(resolve, 500)); return COUNTRY_OPTIONS; }} /> ); };
ComboboxMulti
Use the ComboboxMulti
component when users can choose multiple items from a predefined list of options.
() => { const [value, setValue] = React.useState([]); return ( <ComboboxMulti label="Select country" hint="Start typing to see results" value={value} onChange={setValue} options={COUNTRY_OPTIONS} /> ); };
Should you wish to apply maxWidth
to a ComboboxMulti
, ensure the block
prop is set to false
.
() => { const [value, setValue] = React.useState([]); return ( <ComboboxMulti label="Select country" hint="Start typing to see results" value={value} onChange={setValue} options={COUNTRY_OPTIONS} maxWidth="lg" block={false} /> ); };
ComboboxAsyncMulti
Use the ComboboxAsyncMulti
component when users can choose multiple items from a list of options that needs to be fetched over the network.
() => { const [value, setValue] = React.useState([]); return ( <ComboboxAsyncMulti label="Select country" hint="Start typing to see results" value={value} onChange={setValue} loadOptions={async function loadOptions(inputValue) { // Simulate a slow network call await new Promise((resolve) => setTimeout(resolve, 500)); return COUNTRY_OPTIONS; }} /> ); };
Block
Use the block
prop to expand the component to fill the available space.
() => { const [value, setValue] = React.useState(null); return ( <Combobox label="Select country" hint="Start typing to see results" block value={value} onChange={setValue} options={COUNTRY_OPTIONS} /> ); };
Required
The required
prop can be used to indicate that user input is required on the field before a form can be submitted.
Required fields do not append ‘(optional)’ to the label and also use aria-required to indicate to screen readers that the field is required.
Hide optional label
The hideOptionalLabel
prop can be used in situations where you want to indicate to screen reader users that a field is optional but don’t want to show the ‘(optional)’ label.
The usage of hideOptionalLabel
should be reserved for inputs that filter data in a table or chart, and should never be used in standard forms for submitting information.
() => { const [value, setValue] = React.useState(null); return ( <Combobox label="Select country" hint="Start typing to see results" hideOptionalLabel value={value} onChange={setValue} options={COUNTRY_OPTIONS} /> ); };
Invalid
Use the invalid
prop to indicate if the user input is invalid. An example where this shoud be applied is when ‘All fields are required unless marked optional’.
() => { const [value, setValue] = React.useState(null); const invalid = !value; return ( <Combobox label="Select country" hint="Start typing to see results" required invalid={invalid} message={invalid ? 'Country is required' : undefined} value={value} onChange={setValue} options={COUNTRY_OPTIONS} /> ); };
Disabled
Disabled input elements are unusable and can not be clicked. This prevents a user from interacting with the input element until another action is complete.
() => { const [value, setValue] = React.useState(null); return ( <Combobox label="Select country" hint="Start typing to see results" disabled value={value} onChange={setValue} options={COUNTRY_OPTIONS} /> ); };
Clearable
Use the clearable
prop to render a clear ("x") button when there is a selected option.
() => { const [value, setValue] = React.useState(null); return ( <Combobox label="Select country" hint="Start typing to see results" value={value} onChange={setValue} options={COUNTRY_OPTIONS} clearable /> ); };
Custom rendering
Use the renderItem
prop to customise how each option in the dropdown list is rendered. Inside this function, you can make use of the ComboboxRenderItem
component to style extra information.
Note: When you are using this prop, you still need to assign a label
and value
to every option.
() => { const [value, onChange] = React.useState(null); return ( <Combobox label="Search users" hint="Start typing to see results" value={value} onChange={onChange} options={NAME_OPTIONS} renderItem={(item) => ( <ComboboxRenderItem itemLabel={item.label} secondaryText={`Role: ${item.jobTitle}`} tertiaryText={`Job: ${item.status}`} beforeElement={ <Avatar name={item.fullName} size="sm" tone="action" /> } endElement={ item.unreadMessageCount > 0 ? ( <NotificationBadge value={item.unreadMessageCount} tone="action" /> ) : null } /> )} /> ); };
Handling large datasets
While we don’t recommend putting extremely large datasets as Combobox options, all of the Combobox components should comfortably handle many options and cater for most, standard use-cases.
If you would like to see how Combobox performs with various option lengths, you can use the example below.
() => { const generateOptions = (number) => { const result = []; for (let i = 0; i < number; i++) { const countryIndex = i % COUNTRY_OPTIONS.length; const countryName = `${COUNTRY_OPTIONS[countryIndex].label} ${ Math.floor(i / COUNTRY_OPTIONS.length) + 1 }`; result.push({ label: countryName, value: countryName }); } return result; }; const [numOfOptions, setNumOfOptions] = React.useState(1000); const [options, setOptions] = React.useState(generateOptions(numOfOptions)); const [comboboxValue, setComboboxValue] = React.useState(null); React.useEffect(() => { setOptions(generateOptions(numOfOptions)); }, [numOfOptions]); return ( <FormStack> <TextInput label="Number of country options" maxWidth="sm" onChange={(event) => { setNumOfOptions(event.target.valueAsNumber); }} required type="number" value={numOfOptions} /> <Combobox label="Select country" hint="Start typing to see results" value={comboboxValue} onChange={setComboboxValue} options={options} /> </FormStack> ); };
Related components
- Autocomplete – Autocomplete, also known as type-ahead, uses predictive text to help select options as a user types.
- Dropdown menu – A dropdown menu displays a list of actions when a trigger is pressed.
- Select – Select provides a way for users to choose one item from a collapsible list. It helps reduce input errors and screen space.
- Text input – This component allows users to enter free-form text.
Related patterns
- Selecting multiple options – Multi-select is a commonly used design pattern that allows users to select multiple options from a list. This pattern is used in various contexts such as search filters, form fields, and more.