Skip to main contentSkip to docs navigation

Autocomplete

A button-trigger combobox — opens a searchable option list from a toggle, with single- or multi-select and grouped items.

Overview

Autocomplete is chassis-css's button-trigger combobox — a display-only toggle that opens a panel containing its own search field, rather than a text input that's itself the trigger. That's the difference from Combobox: there, the text input is the combobox; here, the toggle just opens one. Compose an AutocompleteItem per option, each identified by an id, optionally grouped with AutocompleteGroup. Pass placeholder for the toggle's empty-state text and searchPlaceholder for the search field inside the panel.

JSX
import { Autocomplete, AutocompleteItem } from '@chassis-ui/react'

export const Example = () => {
  return (
    <Autocomplete aria-label="Fruit" placeholder="Select a fruit…">
      <AutocompleteItem id="apple">Apple</AutocompleteItem>
      <AutocompleteItem id="banana">Banana</AutocompleteItem>
      <AutocompleteItem id="cherry">Cherry</AutocompleteItem>
      <AutocompleteItem id="grape">Grape</AutocompleteItem>
      <AutocompleteItem id="mango">Mango</AutocompleteItem>
    </Autocomplete>
  )
}

Multiple selection

Set multiple to allow more than one option to be selected. The toggle shows the single selection's label, or an "N selected" count once more than one is picked, and the panel stays open after each selection so more can be picked. Backspace in the empty search field removes the last selected option.

JSX
import { Autocomplete, AutocompleteItem } from '@chassis-ui/react'

export const Example = () => {
  return (
    <Autocomplete aria-label="Fruit" placeholder="Select fruits…" multiple>
      <AutocompleteItem id="apple">Apple</AutocompleteItem>
      <AutocompleteItem id="banana">Banana</AutocompleteItem>
      <AutocompleteItem id="cherry">Cherry</AutocompleteItem>
      <AutocompleteItem id="grape">Grape</AutocompleteItem>
      <AutocompleteItem id="mango">Mango</AutocompleteItem>
    </Autocomplete>
  )
}

Rich item content

Add icon/description to an AutocompleteItem for a leading icon and a secondary line of text below the label.

JSX
import { Autocomplete, Icon, AutocompleteItem } from '@chassis-ui/react'

export const Example = () => {
  return (
    <Autocomplete aria-label="Role" placeholder="Choose a role…">
      <AutocompleteItem
        id="admin"
        icon={<Icon name="shield-outline" size={16} />}
        description="Full access to every setting"
      >
        Admin
      </AutocompleteItem>
      <AutocompleteItem
        id="editor"
        icon={<Icon name="gear-outline" size={16} />}
        description="Can edit content, not settings"
      >
        Editor
      </AutocompleteItem>
      <AutocompleteItem
        id="viewer"
        icon={<Icon name="eye-outline" size={16} />}
        description="Read-only access"
      >
        Viewer
      </AutocompleteItem>
    </Autocomplete>
  )
}

Grouped items

Wrap related AutocompleteItem elements in an AutocompleteGroup to render them under a shared header.

JSX
import { Autocomplete, AutocompleteGroup, AutocompleteItem } from '@chassis-ui/react'

export const Example = () => {
  return (
    <Autocomplete aria-label="Language" placeholder="Choose a language…">
      <AutocompleteGroup label="Frontend">
        <AutocompleteItem id="html">HTML</AutocompleteItem>
        <AutocompleteItem id="css">CSS</AutocompleteItem>
        <AutocompleteItem id="js">JavaScript</AutocompleteItem>
      </AutocompleteGroup>
      <AutocompleteGroup label="Backend">
        <AutocompleteItem id="python">Python</AutocompleteItem>
        <AutocompleteItem id="ruby">Ruby</AutocompleteItem>
      </AutocompleteGroup>
      <AutocompleteItem id="sql">SQL</AutocompleteItem>
    </Autocomplete>
  )
}

Disabled options

Add disabled to an AutocompleteItem to remove it from keyboard navigation and prevent it from being selected.

JSX
import { Autocomplete, AutocompleteItem } from '@chassis-ui/react'

export const Example = () => {
  return (
    <Autocomplete aria-label="Role" placeholder="Choose a role…">
      <AutocompleteItem id="admin">Admin</AutocompleteItem>
      <AutocompleteItem id="editor" disabled>
        Editor (unavailable)
      </AutocompleteItem>
      <AutocompleteItem id="viewer">Viewer</AutocompleteItem>
    </Autocomplete>
  )
}

Data-driven items

Pass an items array instead of composing children to build the option list from data. A 'header' entry starts a group that every following item joins until the next header or the end of the array.

JSX
import { Autocomplete } from '@chassis-ui/react'

export const Example = () => {
  return (
    <Autocomplete
      aria-label="Timezone"
      placeholder="Choose a timezone…"
      items={[
        { type: 'header', id: 'americas', label: 'Americas' },
        { id: 'est', label: 'Eastern Time' },
        { id: 'cst', label: 'Central Time' },
        { type: 'header', id: 'europe', label: 'Europe' },
        { id: 'gmt', label: 'Greenwich Mean Time' },
        { id: 'cet', label: 'Central European Time' }
      ]}
    />
  )
}

As a form field

Pass label/help to wrap the autocomplete in a .form-field with an associated FormLabel and FormHelp. Pass name to have Autocomplete create and manage hidden <input>s for native form submission — one in single-select mode, one per selected key in multiple mode.

With required, an autocomplete with nothing selected holds its form back from submitting: the toggle takes focus and shows as invalid, with its invalidFeedback, until an option is selected or the form is reset. invalid, once set, and valid decide how it looks instead.

The billing region.
JSX
import { Autocomplete, AutocompleteItem } from '@chassis-ui/react'

export const Example = () => {
  return (
    <Autocomplete
      label="Country"
      help="The billing region."
      name="country"
      placeholder="Pick a country…"
    >
      <AutocompleteItem id="us">United States</AutocompleteItem>
      <AutocompleteItem id="uk">United Kingdom</AutocompleteItem>
      <AutocompleteItem id="ca">Canada</AutocompleteItem>
      <AutocompleteItem id="au">Australia</AutocompleteItem>
      <AutocompleteItem id="de">Germany</AutocompleteItem>
    </Autocomplete>
  )
}

Controlled selection

Pass value/onChange to control the selection directly — an array when multiple is set, a single id otherwise. Omit them (use defaultValue instead) to let Autocomplete manage selection internally.

Accessibility

Opening the panel moves focus to the search field; closing it — via Escape, a selection, or an outside click — returns focus to the toggle. The toggle renders as a <div role="button"> rather than a native <button>: an earlier version rendered removable chips for each selection directly inside it, which failed an automated accessibility check for nesting interactive controls inside a button, so selections now render as plain text instead and the non-native trigger stays in place.

Scope

  • No typeahead while closed. Unlike a native <select>, there's no way to jump to an option by typing a letter before opening the panel — the search field only exists once the toggle has been activated.
  • No async filtering. Matching happens entirely client-side against the options already passed as children/items; there's no controlled input value or onInputChange callback to drive a server-side search.

API

Autocomplete

PropTypeDefault
aria-label?string—
An accessible label for the autocomplete, used when there's no visible <label>.
aria-labelledby?string—
Identifies a visible <label> element for the autocomplete.
children?ReactNode—
AutocompleteItem elements, optionally wrapped in AutocompleteGroup — read as data by Autocomplete to build the option list. Not rendered directly. Ignored when items is set.
className?string—
A string of all className you want applied to the base component.
defaultValue?Key | Key[] | null—
The initial selected option's id(s) (uncontrolled). An array when multiple is set.
disabled?boolean—
Prevents the autocomplete from being focused or interacted with.
help?ReactNode—
A description for the field, rendered below the autocomplete.
id?string—
id forwarded to the search input inside the popover. The toggle — the field's real, always-focusable surface — has no single labelable element <label for> can target (it's a role="button" <div>, and the search input itself is hidden until open), so label is associated via aria-labelledby on the toggle instead. See FORMS.md's "role=group" pattern.
invalid?boolean—
Set component validation state to invalid.
invalidFeedback?ReactNode—
An error message for the field, rendered below the autocomplete when invalid is set, and after a submit that a required autocomplete with nothing selected held back.
items?MenuItemsDef—
Array of item/header/divider definitions for data-driven rendering. When provided, children are ignored. A 'header' entry starts a group that all following items join until the next header or the end of the array. 'divider' entries are a no-op here — use AutocompleteGroup composition instead if you need finer control over grouping. An entry's href/onClick are Menu-only and are not read here — use onChange to react to the selection instead.
label?ReactNode—
The field's caption, rendered as a FormLabel associated with the toggle.
multiple?booleanfalse
Allows more than one option to be selected. The toggle shows the single selection's label, or an "N selected" count once more than one is picked. The menu stays open after each selection, and Backspace in the empty search field removes the last selected option.
name?string—
name of auto-created hidden input(s), kept in sync with the selection, for native form submission. Single-select renders one; multiple renders one per selected key. Omit to skip hidden-input creation.
noResultsText?ReactNodeNo results found
Text shown in the listbox when no options match the current query.
onChange?((value: Key | Key[] | null) => void)—
Callback fired when the selection changes. Receives an array of keys when multiple is set.
placeholder?string—
Text shown on the toggle when nothing is selected.
required?boolean—
Toggle the required state for the component. A required autocomplete with nothing selected holds its form back from submitting, takes focus on its toggle and shows as invalid, with invalidFeedback, until an option is selected or the form is reset. invalid, once set, and valid decide how it looks instead.
searchPlaceholder?string—
Placeholder for the search field inside the dropdown.
size?"sm" | "lg"—
Size the component sm or lg.
valid?boolean—
Set component validation state to valid.
validFeedback?ReactNode—
A success message for the field, rendered below the autocomplete when valid is set.
value?Key | Key[] | null—
The selected option's id(s) (controlled). An array when multiple is set.

AutocompleteItem

PropTypeDefault
childrenReactNode—
Content of the option. Used as the filter/typeahead text when textValue isn't set — pass textValue explicitly whenever children isn't a plain string (e.g. it wraps an icon or other rich markup), since it can't otherwise be derived from rich content.
description?ReactNode—
Secondary line of text rendered below children (.menu-item-description).
disabled?boolean—
Prevents the option from being selected, focused, or otherwise interacted with.
icon?ReactNode—
Icon rendered at the option's leading edge (.menu-item-icon).
idKey—
Identifies this option. Submitted as the value when this option is selected.
textValue?string—
Text used for filtering and typeahead. Required when children isn't a plain string — falls back to children itself when omitted and children is a string.

AutocompleteGroup

PropTypeDefault
childrenReactNode—
Items belonging to this group.
labelReactNode—
Header content for the group (.menu-header).