# Autocomplete

Suggests matching options while keeping the input free to accept custom text.

Page: https://sui.draco.dev/docs/components/autocomplete

Autocomplete combines a text input with a filtered list of suggestions. Its value is the input text, so users can accept a suggestion or enter their own answer. For a selection that must stay within a list of options, use [Combobox](/docs/components/combobox).

### Example: autocomplete-demo

```tsx
import {
  Autocomplete,
  AutocompleteClear,
  AutocompleteContent,
  AutocompleteEmpty,
  AutocompleteInput,
  AutocompleteInputGroup,
  AutocompleteItem,
  AutocompleteList,
  AutocompleteTrigger,
} from "@workspace/ui/components/autocomplete";
import {
  Field,
  FieldDescription,
  FieldLabel,
} from "@workspace/ui/components/field";
import { InputGroupAddon } from "@workspace/ui/components/input-group";
import { useId, useState } from "react";
import type { ExampleProps } from "../types";

export default function AutocompleteDemo({ locale }: ExampleProps) {
  const chinese = locale === "zh-CN";
  const id = useId();
  const [query, setQuery] = useState("");
  const cities = chinese
    ? ["北京", "上海", "杭州", "成都", "深圳"]
    : ["Beijing", "Shanghai", "Hangzhou", "Chengdu", "Shenzhen"];

  return (
    <Field className="w-full max-w-sm">
      <FieldLabel htmlFor={id}>{chinese ? "目的地" : "Destination"}</FieldLabel>
      <Autocomplete
        items={cities}
        value={query}
        onValueChange={setQuery}
        openOnInputClick
      >
        <AutocompleteInputGroup>
          <AutocompleteInput
            id={id}
            placeholder={chinese ? "选择或输入城市" : "Choose or type a city"}
          />
          <InputGroupAddon align="inline-end">
            <AutocompleteClear
              aria-label={chinese ? "清空目的地" : "Clear destination"}
            />
            <AutocompleteTrigger
              aria-label={chinese ? "显示城市建议" : "Show city suggestions"}
            />
          </InputGroupAddon>
        </AutocompleteInputGroup>
        <AutocompleteContent>
          <AutocompleteEmpty>
            {chinese
              ? "没有匹配的城市，仍可使用你输入的名称"
              : "No matching cities. You can still use your own text."}
          </AutocompleteEmpty>
          <AutocompleteList>
            {(city: string) => (
              <AutocompleteItem key={city} value={city}>
                {city}
              </AutocompleteItem>
            )}
          </AutocompleteList>
        </AutocompleteContent>
      </Autocomplete>
      <FieldDescription>
        {chinese
          ? "城市建议不会限制自由输入。使用方向键浏览，Enter 采用建议，Escape 关闭"
          : "Suggestions do not restrict your input. Use arrow keys to browse, Enter to accept, and Escape to close."}
      </FieldDescription>
      <output className="text-muted-foreground text-sm" aria-live="polite">
        {chinese ? "当前输入" : "Current input"}: {query || "—"}
      </output>
    </Field>
  );
}
```

## Installation

```bash
bunx --bun shadcn@latest add @sui/autocomplete
```

Install with the shadcn CLI or use the shared `@workspace/ui` package. Follow the [installation guide](/docs/installation) to configure the registry, load styles, and choose import aliases.

## Usage

```tsx showLineNumbers
import {
  Autocomplete,
  AutocompleteContent,
  AutocompleteEmpty,
  AutocompleteInput,
  AutocompleteInputGroup,
  AutocompleteItem,
  AutocompleteList,
} from "@workspace/ui/components/autocomplete"
import { Field, FieldLabel } from "@workspace/ui/components/field"

const languages = ["TypeScript", "JavaScript", "Rust"]

<Field>
  <FieldLabel>Project language</FieldLabel>
  <Autocomplete items={languages} openOnInputClick>
    <AutocompleteInputGroup>
      <AutocompleteInput aria-label="Project language" placeholder="Choose or type a language" />
    </AutocompleteInputGroup>
    <AutocompleteContent>
      <AutocompleteEmpty>No suggestions found.</AutocompleteEmpty>
      <AutocompleteList>
        {(language: string) => (
          <AutocompleteItem key={language} value={language}>
            {language}
          </AutocompleteItem>
        )}
      </AutocompleteList>
    </AutocompleteContent>
  </Autocomplete>
</Field>
```

## Suggestions and clearing

Use `AutocompleteInputGroup` to anchor the popup to the complete input. Add `AutocompleteTrigger` and `AutocompleteClear` inside an `InputGroupAddon` when the field needs explicit suggestion and clear buttons. Give icon controls accessible labels.

Pass `value` and `onValueChange` to `Autocomplete` for a controlled text input. `openOnInputClick` also shows suggestions when the input is clicked. `autoHighlight` highlights the first match after typing; `mode="both"` enables inline completion alongside filtering.

## Grouped suggestions

Provide groups with an `items` array, render each group inside `AutocompleteList`, and use `AutocompleteCollection` to render its items. For object items, `itemToStringValue` defines the text placed in the input.

### Example: autocomplete-grouped

```tsx
import {
  Autocomplete,
  AutocompleteCollection,
  AutocompleteContent,
  AutocompleteEmpty,
  AutocompleteGroup,
  AutocompleteGroupLabel,
  AutocompleteInput,
  AutocompleteInputGroup,
  AutocompleteItem,
  AutocompleteList,
} from "@workspace/ui/components/autocomplete";
import { Field, FieldLabel } from "@workspace/ui/components/field";
import { useId } from "react";
import type { ExampleProps } from "../types";

interface Destination {
  id: string;
  label: string;
}
interface DestinationGroup {
  value: string;
  items: Destination[];
}

export default function AutocompleteGrouped({ locale }: ExampleProps) {
  const chinese = locale === "zh-CN";
  const id = useId();
  const groups: DestinationGroup[] = [
    {
      value: chinese ? "亚洲" : "Asia",
      items: [
        { id: "tokyo", label: chinese ? "东京" : "Tokyo" },
        { id: "singapore", label: chinese ? "新加坡" : "Singapore" },
      ],
    },
    {
      value: chinese ? "欧洲" : "Europe",
      items: [
        { id: "paris", label: chinese ? "巴黎" : "Paris" },
        { id: "london", label: chinese ? "伦敦" : "London" },
      ],
    },
  ];

  return (
    <Field className="w-full max-w-sm">
      <FieldLabel htmlFor={id}>
        {chinese ? "按地区浏览目的地" : "Browse destinations by region"}
      </FieldLabel>
      <Autocomplete
        items={groups}
        itemToStringValue={(item) => item.label}
        openOnInputClick
        autoHighlight
      >
        <AutocompleteInputGroup>
          <AutocompleteInput
            id={id}
            placeholder={chinese ? "搜索城市" : "Search cities"}
          />
        </AutocompleteInputGroup>
        <AutocompleteContent>
          <AutocompleteEmpty>
            {chinese ? "没有找到城市" : "No cities found."}
          </AutocompleteEmpty>
          <AutocompleteList>
            {(group: DestinationGroup) => (
              <AutocompleteGroup key={group.value} items={group.items}>
                <AutocompleteGroupLabel>{group.value}</AutocompleteGroupLabel>
                <AutocompleteCollection>
                  {(destination: Destination) => (
                    <AutocompleteItem key={destination.id} value={destination}>
                      {destination.label}
                    </AutocompleteItem>
                  )}
                </AutocompleteCollection>
              </AutocompleteGroup>
            )}
          </AutocompleteList>
        </AutocompleteContent>
      </Autocomplete>
    </Field>
  );
}
```

## Disabled controls and items

Set `disabled` on `Autocomplete` to disable the input and its controls. Set `disabled` on a particular `AutocompleteItem` to leave it visible without allowing interaction. Use the switch below to enable the field; the Go suggestion remains unavailable.

### Example: autocomplete-disabled

```tsx
import {
  Autocomplete,
  AutocompleteContent,
  AutocompleteEmpty,
  AutocompleteInput,
  AutocompleteInputGroup,
  AutocompleteItem,
  AutocompleteList,
  AutocompleteTrigger,
} from "@workspace/ui/components/autocomplete";
import {
  Field,
  FieldDescription,
  FieldGroup,
  FieldLabel,
} from "@workspace/ui/components/field";
import { InputGroupAddon } from "@workspace/ui/components/input-group";
import { Switch } from "@workspace/ui/components/switch";
import { useId, useState } from "react";
import type { ExampleProps } from "../types";

export default function AutocompleteDisabled({ locale }: ExampleProps) {
  const chinese = locale === "zh-CN";
  const unavailableLabel = chinese ? "（暂不可用）" : " (unavailable)";
  const id = useId();
  const switchId = useId();
  const [disabled, setDisabled] = useState(true);
  const languages = ["TypeScript", "JavaScript", "Rust", "Go"];

  return (
    <FieldGroup className="w-full max-w-sm">
      <Field orientation="horizontal">
        <Switch
          id={switchId}
          checked={disabled}
          onCheckedChange={setDisabled}
        />
        <FieldLabel htmlFor={switchId}>
          {chinese ? "禁用建议输入框" : "Disable autocomplete"}
        </FieldLabel>
      </Field>
      <Field data-disabled={disabled}>
        <FieldLabel htmlFor={id}>
          {chinese ? "项目语言" : "Project language"}
        </FieldLabel>
        <Autocomplete
          items={languages}
          disabled={disabled}
          defaultValue="TypeScript"
          openOnInputClick
        >
          <AutocompleteInputGroup>
            <AutocompleteInput id={id} />
            <InputGroupAddon align="inline-end">
              <AutocompleteTrigger
                aria-label={
                  chinese ? "显示语言建议" : "Show language suggestions"
                }
              />
            </InputGroupAddon>
          </AutocompleteInputGroup>
          <AutocompleteContent>
            <AutocompleteEmpty>
              {chinese ? "没有匹配的语言" : "No matching languages."}
            </AutocompleteEmpty>
            <AutocompleteList>
              {(language: string) => (
                <AutocompleteItem
                  key={language}
                  value={language}
                  disabled={language === "Go"}
                >
                  {language}
                  {language === "Go" ? unavailableLabel : ""}
                </AutocompleteItem>
              )}
            </AutocompleteList>
          </AutocompleteContent>
        </Autocomplete>
        <FieldDescription>
          {chinese
            ? "开启控件后可以输入和浏览建议。Go 选项保持禁用"
            : "Enable the control to type and browse suggestions. The Go option stays disabled."}
        </FieldDescription>
      </Field>
    </FieldGroup>
  );
}
```

## Accessibility and keyboard

Provide a visible `FieldLabel` or an `aria-label` for the input. When linking a label explicitly, use React `useId()` so examples and repeated fields keep independent IDs.

Type to filter suggestions. Arrow keys move the highlighted suggestion, Enter accepts it, and Escape closes the popup. A disabled suggestion cannot be accepted. Suggestions do not make custom text invalid; add application validation when the field needs it.

## API reference

| Part | Purpose |
| --- | --- |
| `Autocomplete` | Owns items, filtering, input `value`, `onValueChange`, `mode`, opening, and disabled state. |
| `AutocompleteInputGroup`, `AutocompleteInput` | Compose the styled input and its anchor. The input keeps standard input props and a React 19 `ref`. |
| `AutocompleteTrigger`, `AutocompleteClear` | Open the suggestion popup or clear the input. Both support `render` composition. |
| `AutocompleteContent` | Composes the portal and positioning. Defaults to bottom/start with a `sideOffset` of `6`; accepts `side`, `align`, offsets, and `anchor`. |
| `AutocompleteList`, `AutocompleteItem` | Render filtered suggestions with keyboard highlighting and per-item `disabled`. |
| `AutocompleteGroup`, `AutocompleteGroupLabel`, `AutocompleteCollection` | Render labeled groups and their filtered items. |
| `AutocompleteEmpty`, `AutocompleteStatus`, `AutocompleteSeparator` | Show empty results, accessible status, and visual separators. |
| `AutocompleteValue` | Render the current input text with a child render function. |
| `useAutocompleteFilter`, `useAutocompleteFilteredItems` | Reuse filtering helpers for custom matching or externally filtered lists. |

See the [Base UI Autocomplete API](https://base-ui.com/react/components/autocomplete#api-reference) for the primitive props and event details.
