هذه الصفحة غير مترجمة بعد، وهي معروضة بالإنجليزية.

The slotsmith Autocomplete is a React combobox and select in one component: it filters as you type, or works as a plain select with typeahead. It takes one value or several, remote options, a create row and virtual lists. Every part it renders is a slot you can replace.

Overview

The demo below uses the fallbacks only. Open a picker with the mouse or with ↓, type to filter, and pick with Enter. The topics picker keeps several values as tags; its last topic is archived and cannot be picked.

Country

Topics

Country: none

Topics: Accessibility, Forms

Each feature has a guide with its own live demo: select or combobox with auto highlight, search in the trigger, multiple values, groups and separators, remote options with debounce, cancellation and paging, the loading, empty and error states, validation, creatable options, virtual lists for long lists, and the compound parts for your own layout.

Install

npm i slotsmith

VirtualAutocomplete from slotsmith/virtual also needs @tanstack/react-virtual.

import "slotsmith/autocomplete.css";

Import the stylesheet once, at your app's entry. slotsmith/styles.css holds every component's styles instead.

Quick start

Pass options, value and onChange, and name the combobox with aria-label or aria-labelledby. Options with value and label (or id and name) need no further props.

Guides

  • Select or comboboxUse the slotsmith Autocomplete as a combobox that filters as you type, or as a select with typeahead, by switching one prop.
  • Search in the triggerPut the slotsmith Autocomplete's search box inside the trigger with searchIn="trigger": an editable combobox, its single and multiple modes, keys and IME.
  • Multiple valuesPick several values with the slotsmith Autocomplete: tags in the trigger, Backspace to remove the last one, and an overflow count.
  • Groups and separatorsGroup the slotsmith Autocomplete's options under labels with getOptionGroup: group order, groups that span pages, virtual lists and the ARIA roles.
  • Remote optionsLoad the slotsmith Autocomplete's options from a server with useAsyncOptions: debounced, cancelled when superseded, and paged.
  • Loading, empty and error statesWhat the slotsmith Autocomplete shows instead of options: the loading, empty, minimum-characters and error rows, and how to change them.
  • ValidationShow a failed check on the slotsmith Autocomplete: the invalid prop, an error message tied to the combobox, and the label and message styles your app adds.
  • Creatable optionsLet people add a missing option from the slotsmith Autocomplete's search: the create row, onCreate, and a pending create.
  • Virtual listsShow thousands of options in the slotsmith Autocomplete with the virtual prop, which renders only the options in view.
  • Compound partsLay out the slotsmith Autocomplete yourself with Autocomplete.Provider and its parts, read its state from the context, or use the useAutocomplete hook.

Reference

The API page is generated from the library’s source, so it lists every slot, prop and label the installed version has.

Adapters

The autocomplete works with any design system. Each slot takes a component, so a library’s own popover surface, input, tag and menu item can replace the fallbacks. The Adapters page has ready slot maps for shadcn/ui, MUI, Chakra, Ant Design and Radix Themes, as examples of well-known libraries; the same approach works with your own.

Accessibility

The autocomplete follows the ARIA combobox pattern, with the listbox in a popup:

  • The trigger is the element with role="combobox". It is in the tab order, and carries aria-expanded, aria-haspopup="listbox" and, while open, aria-controls pointing at the list. The naming and validation attributes you pass to Autocomplete (aria-label, aria-labelledby, aria-describedby, aria-invalid, aria-required and the like, plus id) go to this element, not to the wrapper.
  • The search box gets focus when the popup opens. It has role="searchbox", aria-autocomplete="list", and is named by the search label. See select or combobox.
  • Search in the trigger. With searchIn="trigger" the combobox is an input inside the trigger, the WAI-ARIA 1.2 editable combobox. It carries role="combobox", aria-autocomplete="list", aria-expanded, aria-activedescendant and the naming props, keeps focus while the list is open, and a <label for> names it. The chevron is a button outside the tab order, named by the toggle label. See search in the trigger.
  • The highlight is announced through aria-activedescendant: on the search box, or on the trigger itself when searchable is false, so focus never leaves the field while you move through the options.
  • The list has role="listbox", with aria-multiselectable="true" in multiple mode and aria-busy="true" while loading is set: with useAsyncOptions, while each search loads its first page, even when the last options still show. Loading more at the end of the list does not set it. Each option has role="option" and aria-selected; an option ruled out by optionDisabled has aria-disabled="true" and the arrow keys skip it. See multiple values.
  • Groups. With getOptionGroup, each group has role="group" and is named by its label through aria-labelledby. The line between groups is hidden from assistive technology. See groups and separators.
  • Invalid values. invalid sets aria-invalid="true" on the combobox, never on the popup’s search box. Point it at your error message with aria-describedby. See validation.
  • Result counts are read out: a visually hidden role="status" region (aria-live="polite") says “12 results” as the list changes, from the results label. It is empty while the popup is closed or shows a status row. See remote options.
  • Tags and clearing. Each tag’s remove button is named by the remove label (“Remove Forms”), and the clear button by clear. Spinners are hidden from assistive technology. See the states.

With focus on the closed trigger (the default, searchIn="popup"):

KeysAction
↓EnterSpaceOpen the popup and highlight the first option.
↑Open the popup and highlight the last option.
A–ZOpen the popup. With searchable set to false, also jump to the first option that starts with the typed letters.

With the popup open:

KeysAction
↓↑Move the highlight, skipping disabled options. It stops at the ends unless loop is set.
HomeEndHighlight the first or the last option.
PgDnPgUpMove the highlight ten options.
EnterPick the highlighted option. With nothing highlighted and a create row offered, create.
EscClose, and move focus back to the trigger.
TabClose, and move focus on as usual.
BackspaceIn multiple mode, with the search box empty, remove the last tag.
A–ZWith searchable set to false: jump to the next option that starts with the typed letters.

With searchIn="trigger" the input keeps the caret, so Space, Home and End stay in the text:

KeysAction
A–ZType into the search. The list opens and narrows.
↓↑Open the list on the first or the last option; with the list open, move the highlight.
Alt+↓Alt+↑Open the list without moving the highlight, or close it.
PgDnPgUpWith the list open: move the highlight ten options.
EnterPick the highlighted option. Nothing is picked while an input method is composing.
EscClose the list and clear the search. In single mode the picked label comes back.
BackspaceIn multiple mode, with the input empty, remove the last tag.

Picking an option in single mode closes the popup and returns focus to the trigger; in multiple mode the popup stays open. A pointer press outside the control closes it. Every label can be translated or replaced; see Labels & locales.

Limitations

FAQ

Is the autocomplete a select or a combobox?

Both. By default it is a combobox: the popup has a search box that filters the options as you type. With searchable set to false it is a select: no search box, and typing a letter jumps to the first option that starts with it.

See it in the docs

Does the autocomplete fetch options itself?

No. It renders the options you pass. For remote options, the useAsyncOptions hook calls your load function with the query, the page and an AbortSignal, and returns the props to spread onto the component: options, loading, error, paging and filter set to false.

See it in the docs

How do I give the autocomplete an accessible name?

Pass aria-label or aria-labelledby to Autocomplete. The naming and validation attributes (id, title, aria-label, aria-labelledby, aria-describedby, aria-details, aria-errormessage, aria-invalid and aria-required) go to the element with role combobox, not to the wrapper.

See it in the docs

Can the autocomplete submit with a plain HTML form?

Yes. Give it a name and it renders one hidden input per selected value. onBlur fires once when focus leaves the whole control, which is when form libraries mark a field as touched.

See it in the docs

Can it show thousands of options?

Yes, with VirtualAutocomplete from slotsmith/virtual, which renders only the options in view. It needs @tanstack/react-virtual ^3.10.0 installed and takes the same props as Autocomplete, plus virtual.

See it in the docs