1. Components
  2. Menus and selection
  3. Combobox

Combobox

Combobox combines a text input with a listbox, allowing users to filter a list of options to items matching a query.

<Combobox>
  <Item>Canada</Item>
  <Item>France</Item>
  <Item>Germany</Item>
  <Item>Spain</Item>
  <Item>Tunisia</Item>
  <Item>United states</Item>
  <Item>United Kingdom</Item>
</Combobox>

Installation

npx dotui-cli@latest add combobox

Usage

Use Combobox to allow users to filter a list of options to items matching a query and select an item from the list.

Options

Label

A visual label can be provided for the combobox using the label prop, or a hidden label using aria-label prop.

<Combobox label="Country">
  <Item>Canada</Item>
  <Item>France</Item>
  <Item>Germany</Item>
  <Item>Spain</Item>
  <Item>Tunisia</Item>
  <Item>United states</Item>
  <Item>United Kingdom</Item>
</Combobox>

Description

A description can be supplied to the combobox via the description prop. The description is always visible unless the validationState is “invalid” and an error message is provided.

Please select a country.
<Combobox label="Country" description="Please select a country.">
  <Item>Canada</Item>
  <Item>France</Item>
  <Item>Germany</Item>
  <Item>Spain</Item>
  <Item>Tunisia</Item>
  <Item>United states</Item>
  <Item>United Kingdom</Item>
</Combobox>

Validation

An errorMessage can be supplied to a Combobox, which will be displayed when the isInvalid prop is set to true.

Please select a country in the list.
<Combobox isInvalid errorMessage="Please select a country in the list.">
  <Item>Canada</Item>
  <Item>France</Item>
  <Item>Germany</Item>
  <Item>Spain</Item>
  <Item>Tunisia</Item>
  <Item>United states</Item>
  <Item>United Kingdom</Item>
</Combobox>

Custom value

By default, Combobox doesn't allow users to specify a value that doesn't exist in the list of options and will revert the input value to the current selected value on blur. By specifying allowsCustomValue, this behavior is suppressed.

<Combobox allowsCustomValue>
  <Item>Canada</Item>
  <Item>France</Item>
  <Item>Germany</Item>
  <Item>Spain</Item>
  <Item>Tunisia</Item>
  <Item>United states</Item>
  <Item>United Kingdom</Item>
</Combobox>

Disabled

The isDisabled prop can be used to disable the combobox.

<Combobox label="Favorite animal" isDisabled>
  <Item>Red Panda</Item>
  <Item>Cat</Item>
  <Item>Dog</Item>
  <Item>Aardvark</Item>
  <Item>Kangaroo</Item>
  <Item>Snake</Item>
</Combobox>

Loading

Use the isLoading prop to indicate that the list is loading.

<Combobox label="Favorite Animal" isLoading>
  <Item>Red Panda</Item>
  <Item>Cat</Item>
  <Item>Dog</Item>
  <Item>Aardvark</Item>
  <Item>Kangaroo</Item>
  <Item>Snake</Item>
</Combobox>

Required

Use the isRequired prop to mark the combobox as required. Use the necessityIndicator prop to control the visual style of the required state.

<Combobox label="Country" isRequired necessityIndicator="icon">
  <Item>Canada</Item>
  <Item>France</Item>
  <Item>Germany</Item>
  <Item>Spain</Item>
  <Item>Tunisia</Item>
  <Item>United states</Item>
  <Item>United Kingdom</Item>
</Combobox>

Sections

Combobox supports sections in order to group options. Sections can be used by wrapping groups of items in a Section element.
Sections without a title must provide an aria-label for accessibility.

<Combobox>
  <Section title="Africa">
    <Item>Tunisia</Item>
    <Item>Algeria</Item>
    <Item>Morocco</Item>
  </Section>
  <Section title="America">
    <Item>Canada</Item>
    <Item>United states</Item>
  </Section>
  <Section title="Asia">
    <Item>India</Item>
    <Item>Japan</Item>
    <Item>Korea</Item>
  </Section>
  <Section title="Europe">
    <Item>France</Item>
    <Item>Germany</Item>
    <Item>Spain</Item>
    <Item>United Kingdom</Item>
  </Section>
</Combobox>

Item options

See Item options for more information on the available options.

Uncontrolled

Use defaultSelectedKey to provide a default set of selected item.

<Combobox aria-label="country" defaultSelectedKey="tn">
  <Item id="ca">Canada</Item>
  <Item id="fr">France</Item>
  <Item id="de">Germany</Item>
  <Item id="es">Spain</Item>
  <Item id="tn">Tunisia</Item>
  <Item id="us">United States</Item>
  <Item id="uk">United Kingdom</Item>
</Combobox>

Controlled

Use selectedKey to control the selected item.

You selected: tn

const [country, setCountry] = React.useState<Key | null>("tn");
return (
  <Combobox selectedKey={country} onSelectionChange={setCountry}>
    <Item id="ca">Canada</Item>
    <Item id="fr">France</Item>
    <Item id="de">Germany</Item>
    <Item id="es">Spain</Item>
    <Item id="tn">Tunisia</Item>
    <Item id="us">United States</Item>
    <Item id="uk">United Kingdom</Item>
  </Combobox>
)

Composition

If you need to customize things further, you can drop down to the composition level.

Please choose a framework.
<ComboboxRoot>
  <Label>Framework</Label>
  <ComboboxTrigger />
  <Description>Please choose a framework.</Description>
  <FieldError />
  <Overlay type="popover">
    <ListBox>
      <Item>Next.js</Item>
      <Item>Remix</Item>
      <Item>Gatsby</Item>
      <Item></Item>
    </ListBox>
  </Overlay>
</ComboboxRoot>

Examples

Asynchronous loading

const list = useAsyncList<Character>({
  async load({ signal }) {
    const res = await fetch(`https://pokeapi.co/api/v2/pokemon`, { signal });
    const json = (await res.json()) as { results: Character[] };
    return {
      items: json.results,
    };
  },
});

return (
  <Combobox label="Pokemon" items={list.items} isLoading={list.isLoading}>
    {(item) => <Item id={item.name}>{item.name}</Item>}
  </Combobox>
);

API Reference

PropTypeDefaultDescription
defaultFilter(textValue: string, inputValue: string) => boolean-The filter function used to determine if a option should be included in the combo box list.
formValue'text' | 'key'-Whether the text or key of the selected item is submitted as part of an HTML form. When allowsCustomValue is true, this option does not apply and the text is always submitted.
allowsEmptyCollectionboolean-Whether the combo box allows the menu to be open when the collection is empty.
shouldFocusWrapboolean-Whether keyboard navigation is circular.
defaultItemsIterable<T>-The list of ComboBox items (uncontrolled).
itemsIterable<T>-The list of ComboBox items (controlled).
inputValuestring-The value of the ComboBox input (controlled).
defaultInputValuestring-The default value of the ComboBox input (uncontrolled).
allowsCustomValueboolean-Whether the ComboBox allows a non-item matching input value to be set.
menuTrigger'focus' | 'input' | 'manual''input'The interaction required to display the ComboBox menu.
disabledKeysIterable<Key>-The item keys that are disabled. These items cannot be selected, focused, or otherwise interacted with.
selectedKeyKey | null-The currently selected key in the collection (controlled).
defaultSelectedKeyKey-The initial selected key in the collection (uncontrolled).
isDisabledboolean-Whether the input is disabled.
isReadOnlyboolean-Whether the input can be selected but not changed by the user.
isRequiredboolean-Whether user input is required on the input before form submission.
isInvalidboolean-Whether the input value is invalid.
validate(value: ComboBoxValidationValue) => ValidationError | true | null | undefined-A function that returns an error message if a given value is invalid. Validation errors are displayed to the user when the form is submitted if validationBehavior="native". For realtime validation, use the isInvalid prop instead.
autoFocusboolean-Whether the element should receive focus on render.
namestring-The name of the input element, used when submitting an HTML form.
validationBehavior'native' | 'aria''native'Whether to use native HTML form validation to prevent form submission when the value is missing or invalid, or mark the field as required or invalid via ARIA.
childrenReactNode | (values: ComboBoxRenderProps & {defaultChildren: ReactNode | undefined}) => ReactNode-The children of the component. A function may be provided to alter the children based on component state.
classNamestring-The CSS className for the element.
styleCSSProperties | (values: ComboBoxRenderProps & {defaultStyle: CSSProperties}) => CSSProperties-The inline style for the element. A function may be provided to compute the style based on component state.
EventTypeDescription
onOpenChange(isOpen: boolean) => voidMethod that is called when the open state of the menu changes.
onSelectionChange(key: Key) => voidHandler that is called when the selection changes.
onInputChange(value: string) => voidHandler that is called when the ComboBox input value changes.
onFocus(e: FocusEvent<Target>) => voidHandler that is called when the element receives focus.
onBlur(e: FocusEvent<Target>) => voidHandler that is called when the element loses focus.
onFocusChange(isFocused: boolean) => voidHandler that is called when the element's focus status changes.
onKeyDown(e: KeyboardEvent) => voidHandler that is called when a key is pressed.
onKeyUp(e: KeyboardEvent) => voidHandler that is called when a key is released.
Data attributeDescription
[data-open]Whether the combobox is currently open.
[data-disabled]Whether the combobox is disabled.
[data-invalid]Whether the combobox is invalid.
[data-required]Whether the combobox is required.

Accessibility

Keyboard interactions

KeyDescription
TypingInitiates autocomplete or popover (unless suppressed).
ArrowDown ArrowUpIf the popover is unsuppressed and not already open, the down arrow opens the popover menu.
EscIf the popover is open, close the popover.

Last updated on 10/11/2024

dotUI

Bringing singularity to the web.

Built by mehdibha. The source code is available on GitHub.