Autocomplete
A text input with a popup list of suggestions that filter as you type, letting users quickly find and pick a value.
Examples
With clear and trigger
Compose the input group with AutocompleteInputAddon for a leading icon, plus AutocompleteClear and AutocompleteTrigger buttons.
Sizes
Use the size prop on AutocompleteInputGroup to switch between sm, default, and lg.
With groups
Pass grouped items and render them with AutocompleteGroup, AutocompleteGroupLabel, and AutocompleteCollection.
Async
Fetch suggestions as the user types. Set mode="none" to disable built-in filtering and use AutocompleteStatus to announce loading state.
Installation
Copy the source code below into your project:
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:
| Prop | Type | Default | Description |
|---|---|---|---|
| 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
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | - | 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:
| Prop | Type | Default | Description |
|---|---|---|---|
| positionerProps | BaseAutocomplete.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.