Autocomplete

A text input with a popup list of suggestions that filter as you type, letting users quickly find and pick a value.

AutocompleteExample

Examples

With clear and trigger

Compose the input group with AutocompleteInputAddon for a leading icon, plus AutocompleteClear and AutocompleteTrigger buttons.

AutocompleteWithClearExample

Sizes

Use the size prop on AutocompleteInputGroup to switch between sm, default, and lg.

AutocompleteSizesExample

With groups

Pass grouped items and render them with AutocompleteGroup, AutocompleteGroupLabel, and AutocompleteCollection.

AutocompleteWithGroupsExample

Async

Fetch suggestions as the user types. Set mode="none" to disable built-in filtering and use AutocompleteStatus to announce loading state.

AutocompleteAsyncExample

Installation

Copy the source code below into your project:

tsx
import { Autocomplete as BaseAutocomplete } from "@base-ui/react";
import { cn } from "@/lib/utils";
import { cva } from "class-variance-authority";
import type { VariantProps } from "class-variance-authority";
import { CaretUpDownIcon, XIcon } from "@phosphor-icons/react";

const Autocomplete = BaseAutocomplete.Root;

function AutocompleteValue({ ...props }: BaseAutocomplete.Value.Props) {
  return <BaseAutocomplete.Value data-slot="autocomplete-value" {...props} />;
}

const autocompleteInputGroupVariants = cva(
  "flex w-full min-w-0 items-center gap-1 rounded-lg border border-input bg-gray-950/5 text-foreground transition-all duration-150 focus-within:border-accent focus-within:ring-[3px] focus-within:ring-ring hover:border-accent data-disabled:cursor-not-allowed data-disabled:opacity-50 dark:bg-gray-950/30",
  {
    defaultVariants: {
      size: "default",
    },
    variants: {
      size: {
        sm: "min-h-8 px-2 text-sm",
        default: "min-h-9 px-2 text-sm",
        lg: "min-h-10 px-2.5 text-base",
      },
    },
  },
);

function AutocompleteInputGroup({
  className,
  size,
  ...props
}: BaseAutocomplete.InputGroup.Props & VariantProps<typeof autocompleteInputGroupVariants>) {
  return (
    <BaseAutocomplete.InputGroup
      className={cn(autocompleteInputGroupVariants({ size }), className)}
      data-slot="autocomplete-input-group"
      {...props}
    />
  );
}

function AutocompleteInput({ className, ...props }: BaseAutocomplete.Input.Props) {
  return (
    <BaseAutocomplete.Input
      className={cn(
        "min-w-0 flex-1 bg-transparent py-1 leading-4 outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed",
        className,
      )}
      data-slot="autocomplete-input"
      {...props}
    />
  );
}

function AutocompleteInputAddon({ className, ...props }: React.ComponentProps<"span">) {
  return (
    <span
      className={cn(
        "flex shrink-0 items-center text-muted-foreground select-none [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
        className,
      )}
      data-slot="autocomplete-input-addon"
      {...props}
    />
  );
}

function AutocompleteTrigger({ children, className, ...props }: BaseAutocomplete.Trigger.Props) {
  return (
    <BaseAutocomplete.Trigger
      className={cn(
        "flex shrink-0 cursor-default items-center rounded p-0.5 text-muted-foreground transition-colors hover:text-foreground",
        className,
      )}
      data-slot="autocomplete-trigger"
      {...props}
    >
      {children ?? <CaretUpDownIcon className="size-4" />}
    </BaseAutocomplete.Trigger>
  );
}

function AutocompleteClear({ children, className, ...props }: BaseAutocomplete.Clear.Props) {
  return (
    <BaseAutocomplete.Clear
      className={cn(
        "flex shrink-0 cursor-default items-center rounded p-0.5 text-muted-foreground transition-colors hover:text-foreground data-[empty]:invisible",
        className,
      )}
      data-slot="autocomplete-clear"
      {...props}
    >
      {children ?? <XIcon className="size-4" />}
    </BaseAutocomplete.Clear>
  );
}

function AutocompleteContent({
  className,
  positionerProps,
  children,
  ...props
}: BaseAutocomplete.Popup.Props & {
  positionerProps?: BaseAutocomplete.Positioner.Props;
}) {
  return (
    <BaseAutocomplete.Portal>
      <BaseAutocomplete.Positioner
        className={cn(
          "z-10 min-w-(--anchor-width) outline-none select-none",
          positionerProps?.className,
        )}
        sideOffset={8}
        {...positionerProps}
      >
        <BaseAutocomplete.Popup
          className={cn(
            "group max-h-(--available-height) origin-(--transform-origin) overflow-y-auto rounded-xl bg-popover p-1.5 text-popover-foreground shadow-lg outline outline-border transition-[transform,scale,opacity] data-ending-style:scale-90 data-ending-style:opacity-0 data-starting-style:scale-90 data-starting-style:opacity-0 dark:shadow-none",
            className,
          )}
          data-slot="autocomplete-popup"
          {...props}
        >
          {children}
        </BaseAutocomplete.Popup>
      </BaseAutocomplete.Positioner>
    </BaseAutocomplete.Portal>
  );
}

function AutocompleteList({ className, children, ...props }: BaseAutocomplete.List.Props) {
  return (
    <BaseAutocomplete.List
      className={cn("flex flex-col", className)}
      data-slot="autocomplete-list"
      {...props}
    >
      {children}
    </BaseAutocomplete.List>
  );
}

function AutocompleteItem({ className, children, ...props }: BaseAutocomplete.Item.Props) {
  return (
    <BaseAutocomplete.Item
      className={cn(
        "flex cursor-default items-center gap-2 rounded-lg p-2 text-sm leading-4 outline-none select-none data-disabled:pointer-events-none data-disabled:cursor-not-allowed data-disabled:opacity-50 data-highlighted:bg-primary data-highlighted:text-primary-foreground pointer-coarse:py-2.5 pointer-coarse:text-[0.925rem]",
        className,
      )}
      data-slot="autocomplete-item"
      {...props}
    >
      {children}
    </BaseAutocomplete.Item>
  );
}

function AutocompleteEmpty({ className, children, ...props }: BaseAutocomplete.Empty.Props) {
  return (
    <BaseAutocomplete.Empty
      className={cn("px-2.5 py-2 text-sm text-muted-foreground empty:m-0 empty:p-0", className)}
      data-slot="autocomplete-empty"
      {...props}
    >
      {children}
    </BaseAutocomplete.Empty>
  );
}

function AutocompleteStatus({ className, children, ...props }: BaseAutocomplete.Status.Props) {
  return (
    <BaseAutocomplete.Status
      className={cn("px-2.5 py-2 text-sm text-muted-foreground empty:m-0 empty:p-0", className)}
      data-slot="autocomplete-status"
      {...props}
    >
      {children}
    </BaseAutocomplete.Status>
  );
}

function AutocompleteSeparator(props: BaseAutocomplete.Separator.Props) {
  return (
    <BaseAutocomplete.Separator
      className="-mx-1.5 my-1.5 h-px bg-border"
      data-slot="autocomplete-separator"
      {...props}
    />
  );
}

function AutocompleteGroup({ className, ...props }: BaseAutocomplete.Group.Props) {
  return (
    <BaseAutocomplete.Group
      className={cn("flex flex-col", className)}
      data-slot="autocomplete-group"
      {...props}
    />
  );
}

function AutocompleteGroupLabel({ className, ...props }: BaseAutocomplete.GroupLabel.Props) {
  return (
    <BaseAutocomplete.GroupLabel
      className={cn("px-2 py-1.5 text-xs font-medium text-muted-foreground select-none", className)}
      data-slot="autocomplete-group-label"
      {...props}
    />
  );
}

const AutocompleteCollection = BaseAutocomplete.Collection;
const AutocompleteRow = BaseAutocomplete.Row;

export {
  Autocomplete,
  AutocompleteValue,
  AutocompleteInputGroup,
  AutocompleteInput,
  AutocompleteInputAddon,
  AutocompleteTrigger,
  AutocompleteClear,
  AutocompleteContent,
  AutocompleteList,
  AutocompleteItem,
  AutocompleteEmpty,
  AutocompleteStatus,
  AutocompleteSeparator,
  AutocompleteGroup,
  AutocompleteGroupLabel,
  AutocompleteCollection,
  AutocompleteRow,
};

API Reference

Autocomplete

This component does not add any props on top of Base UI Autocomplete.Root. See the Base UI docs for the full API reference.

AutocompleteInputGroup

The AutocompleteInputGroup component extends the Base UI Autocomplete.InputGroup props and adds the following:

PropTypeDefaultDescription
size"sm" | "default" | "lg""default"Controls the height and text size of the input group.

AutocompleteInput

This component does not add any props on top of Base UI Autocomplete.Input. See the Base UI docs for the full API reference.

AutocompleteInputAddon

PropTypeDefaultDescription
classNamestring-Additional classes for the addon container, used for leading/trailing icons.

AutocompleteTrigger

This component does not add any props on top of Base UI Autocomplete.Trigger. See the Base UI docs for the full API reference.

AutocompleteClear

This component does not add any props on top of Base UI Autocomplete.Clear. See the Base UI docs for the full API reference.

AutocompleteContent

The AutocompleteContent component extends the Base UI Autocomplete.Popup props and adds the following:

PropTypeDefaultDescription
positionerPropsBaseAutocomplete.Positioner.Props-Props forwarded to the underlying Positioner component. Includes align, side, sideOffset, alignOffset, collisionPadding, etc.

AutocompleteList

This component does not add any props on top of Base UI Autocomplete.List. See the Base UI docs for the full API reference.

AutocompleteItem

This component does not add any props on top of Base UI Autocomplete.Item. See the Base UI docs for the full API reference.

AutocompleteValue

This component does not add any props on top of Base UI Autocomplete.Value. See the Base UI docs for the full API reference.

AutocompleteEmpty

This component does not add any props on top of Base UI Autocomplete.Empty. See the Base UI docs for the full API reference.

AutocompleteStatus

This component does not add any props on top of Base UI Autocomplete.Status. See the Base UI docs for the full API reference.

AutocompleteSeparator

This component does not add any props on top of Base UI Autocomplete.Separator. See the Base UI docs for the full API reference.

AutocompleteGroup

This component does not add any props on top of Base UI Autocomplete.Group. See the Base UI docs for the full API reference.

AutocompleteGroupLabel

This component does not add any props on top of Base UI Autocomplete.GroupLabel. See the Base UI docs for the full API reference.