Components
HeroUI v3 Autocomplete is a searchable select that filters a ListBox of options as you type, supporting single and multiple selection with removable tags, grouped sections, disabled options, descriptions, form validation, controlled state, custom trigger values with avatars, and full-width layouts inside a Surface. Built on the real @heroui/react package with @heroui/styles, it composes with SearchField, ListBox, TagGroup, Label, Description, FieldError and useFilter. A thin re-export of the upstream component so consumers install and render the genuine HeroUI primitive.
npx shadcn@latest add https://21st.dev/r/hero_ui/heroui-autocompleteLoading preview...
"use client"
import {
Button,
EmptyState,
FieldError,
Form,
Label,
ListBox,
SearchField,
useFilter,
} from "@heroui/react"
import { Autocomplete } from "@/components/ui/heroui-autocomplete"
export function Required() {
const onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
const formData = new FormData(e.currentTarget)
const data: Record<string, string> = {}
// Convert FormData to plain object
formData.forEach((value, key) => {
data[key] = value.toString()
})
alert("Form submitted successfully!")
}
const { contains } = useFilter({ sensitivity: "base" })
const states = [
{ id: "florida", name: "Florida" },
{ id: "delaware", name: "Delaware" },
{ id: "california", name: "California" },
{ id: "texas", name: "Texas" },
{ id: "new-york", name: "New York" },
{ id: "washington", name: "Washington" },
]
const countries = [
{ id: "usa", name: "United States" },
{ id: "canada", name: "Canada" },
{ id: "mexico", name: "Mexico" },
{ id: "uk", name: "United Kingdom" },
{ id: "france", name: "France" },
{ id: "germany", name: "Germany" },
]
return (
<Form className="flex w-[256px] flex-col gap-4" onSubmit={onSubmit}>
<Autocomplete
isRequired
className="w-full"
name="state"
placeholder="Select one"
selectionMode="single"
>
<Label>State</Label>
<Autocomplete.Trigger>
<Autocomplete.Value />
<Autocomplete.ClearButton />
<Autocomplete.Indicator />
</Autocomplete.Trigger>
<Autocomplete.Popover>
<Autocomplete.Filter filter={contains}>
<SearchField autoFocus name="search" variant="secondary">
<SearchField.Group>
<SearchField.SearchIcon />
<SearchField.Input placeholder="Search states..." />
<SearchField.ClearButton />
</SearchField.Group>
</SearchField>
<ListBox renderEmptyState={() => <EmptyState>No results found</EmptyState>}>
{states.map((state) => (
<ListBox.Item key={state.id} id={state.id} textValue={state.name}>
{state.name}
<ListBox.ItemIndicator />
</ListBox.Item>
))}
</ListBox>
</Autocomplete.Filter>
</Autocomplete.Popover>
<FieldError />
</Autocomplete>
<Autocomplete
isRequired
className="w-full"
name="country"
placeholder="Select a country"
selectionMode="single"
>
<Label>Country</Label>
<Autocomplete.Trigger>
<Autocomplete.Value />
<Autocomplete.ClearButton />
<Autocomplete.Indicator />
</Autocomplete.Trigger>
<Autocomplete.Popover>
<Autocomplete.Filter filter={contains}>
<SearchField autoFocus name="search" variant="secondary">
<SearchField.Group>
<SearchField.SearchIcon />
<SearchField.Input placeholder="Search countries..." />
<SearchField.ClearButton />
</SearchField.Group>
</SearchField>
<ListBox renderEmptyState={() => <EmptyState>No results found</EmptyState>}>
{countries.map((country) => (
<ListBox.Item key={country.id} id={country.id} textValue={country.name}>
{country.name}
<ListBox.ItemIndicator />
</ListBox.Item>
))}
</ListBox>
</Autocomplete.Filter>
</Autocomplete.Popover>
<FieldError />
</Autocomplete>
<Button type="submit">Submit</Button>
</Form>
)
}
export default Required
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...