"use client"
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from "@/components/ui/combobox"
const frameworks = [
"Next.js",
"SvelteKit",
"Nuxt.js",
"Remix",
"Astro",
] as const
export function ComboboxBasic() {
return (
<Combobox items={frameworks}>
<ComboboxInput placeholder="Select a framework" />
<ComboboxContent>
<ComboboxEmpty>No items found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item} value={item}>
{item}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}Installation
npx shadcn@latest add @fulldev/combobox
Usage
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from "@/components/ui/combobox"
const frameworks = ["Next.js", "SvelteKit", "Nuxt.js", "Remix", "Astro"]
export function ExampleCombobox() {
return (
<Combobox items={frameworks}>
<ComboboxInput placeholder="Select a framework" />
<ComboboxContent>
<ComboboxEmpty>No items found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item} value={item}>
{item}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}
Composition
Simple
A single-line input and a flat list (see Basic).
Combobox
├── ComboboxInput
└── ComboboxContent
├── ComboboxEmpty
└── ComboboxList
├── ComboboxItem
└── ComboboxItem
With chips
Multi-select with multiple, chips, and a chips input (see Multiple).
Combobox
├── ComboboxChips
│ ├── ComboboxValue
│ │ └── ComboboxChip
│ └── ComboboxChipsInput
└── ComboboxContent
├── ComboboxEmpty
└── ComboboxList
├── ComboboxItem
└── ComboboxItem
With groups and collection
Nested items per group using ComboboxCollection inside each ComboboxGroup, with a separator between groups (see Groups).
Combobox
├── ComboboxInput
└── ComboboxContent
├── ComboboxEmpty
└── ComboboxList
├── ComboboxGroup
│ ├── ComboboxLabel
│ └── ComboboxCollection
│ ├── ComboboxItem
│ └── ComboboxItem
├── ComboboxSeparator
└── ComboboxGroup
├── ComboboxLabel
└── ComboboxCollection
├── ComboboxItem
└── ComboboxItem
Custom Items
Use itemToStringValue when your items are objects.
import * as React from "react"
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from "@/components/ui/combobox"
type Framework = {
label: string
value: string
}
const frameworks: Framework[] = [
{ label: "Next.js", value: "next" },
{ label: "SvelteKit", value: "sveltekit" },
{ label: "Nuxt", value: "nuxt" },
]
export function ExampleComboboxCustomItems() {
return (
<Combobox
items={frameworks}
itemToStringValue={(framework) => framework.label}
>
<ComboboxInput placeholder="Select a framework" />
<ComboboxContent>
<ComboboxEmpty>No items found.</ComboboxEmpty>
<ComboboxList>
{(framework) => (
<ComboboxItem key={framework.value} value={framework}>
{framework.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}
Multiple Selection
Use multiple with chips for multi-select behavior.
import * as React from "react"
import {
Combobox,
ComboboxChip,
ComboboxChips,
ComboboxChipsInput,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
ComboboxValue,
} from "@/components/ui/combobox"
const frameworks = ["Next.js", "SvelteKit", "Nuxt.js", "Remix", "Astro"]
export function ExampleComboboxMultiple() {
const [value, setValue] = React.useState<string[]>([])
return (
<Combobox
items={frameworks}
multiple
value={value}
onValueChange={setValue}
>
<ComboboxChips>
<ComboboxValue>
{value.map((item) => (
<ComboboxChip key={item}>{item}</ComboboxChip>
))}
</ComboboxValue>
<ComboboxChipsInput placeholder="Add framework" />
</ComboboxChips>
<ComboboxContent>
<ComboboxEmpty>No items found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item} value={item}>
{item}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}
Basic
A simple combobox with a list of frameworks.
"use client"
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from "@/components/ui/combobox"
const frameworks = [
"Next.js",
"SvelteKit",
"Nuxt.js",
"Remix",
"Astro",
] as const
export function ComboboxBasic() {
return (
<Combobox items={frameworks}>
<ComboboxInput placeholder="Select a framework" />
<ComboboxContent>
<ComboboxEmpty>No items found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item} value={item}>
{item}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}Multiple
A combobox with multiple selection using multiple and ComboboxChips.
"use client"
import * as React from "react"
import {
Combobox,
ComboboxChip,
ComboboxChips,
ComboboxChipsInput,
ComboboxContent,
ComboboxEmpty,
ComboboxItem,
ComboboxList,
ComboboxValue,
useComboboxAnchor,
} from "@/components/ui/combobox"
const frameworks = [
"Next.js",
"SvelteKit",
"Nuxt.js",
"Remix",
"Astro",
] as const
export function ComboboxMultiple() {
const anchor = useComboboxAnchor()
return (
<Combobox
multiple
autoHighlight
items={frameworks}
defaultValue={[frameworks[0]]}
>
<ComboboxChips ref={anchor} className="w-full max-w-xs">
<ComboboxValue>
{(values) => (
<React.Fragment>
{values.map((value: string) => (
<ComboboxChip key={value}>{value}</ComboboxChip>
))}
<ComboboxChipsInput />
</React.Fragment>
)}
</ComboboxValue>
</ComboboxChips>
<ComboboxContent anchor={anchor}>
<ComboboxEmpty>No items found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item} value={item}>
{item}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}Clear Button
Use the showClear prop to show a clear button.
"use client"
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from "@/components/ui/combobox"
const frameworks = [
"Next.js",
"SvelteKit",
"Nuxt.js",
"Remix",
"Astro",
] as const
export function ComboboxWithClear() {
return (
<Combobox items={frameworks} defaultValue={frameworks[0]}>
<ComboboxInput placeholder="Select a framework" showClear />
<ComboboxContent>
<ComboboxEmpty>No items found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item} value={item}>
{item}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}Groups
Use ComboboxGroup and ComboboxSeparator to group items.
"use client"
import {
Combobox,
ComboboxCollection,
ComboboxContent,
ComboboxEmpty,
ComboboxGroup,
ComboboxInput,
ComboboxItem,
ComboboxLabel,
ComboboxList,
ComboboxSeparator,
} from "@/components/ui/combobox"
const timezones = [
{
value: "Americas",
items: [
"(GMT-5) New York",
"(GMT-8) Los Angeles",
"(GMT-6) Chicago",
"(GMT-5) Toronto",
"(GMT-8) Vancouver",
"(GMT-3) São Paulo",
],
},
{
value: "Europe",
items: [
"(GMT+0) London",
"(GMT+1) Paris",
"(GMT+1) Berlin",
"(GMT+1) Rome",
"(GMT+1) Madrid",
"(GMT+1) Amsterdam",
],
},
{
value: "Asia/Pacific",
items: [
"(GMT+9) Tokyo",
"(GMT+8) Shanghai",
"(GMT+8) Singapore",
"(GMT+4) Dubai",
"(GMT+11) Sydney",
"(GMT+9) Seoul",
],
},
] as const
export function ComboboxWithGroupsAndSeparator() {
return (
<Combobox items={timezones}>
<ComboboxInput placeholder="Select a timezone" />
<ComboboxContent>
<ComboboxEmpty>No timezones found.</ComboboxEmpty>
<ComboboxList>
{(group, index) => (
<ComboboxGroup key={group.value} items={group.items}>
<ComboboxLabel>{group.value}</ComboboxLabel>
<ComboboxCollection>
{(item) => (
<ComboboxItem key={item} value={item}>
{item}
</ComboboxItem>
)}
</ComboboxCollection>
{index < timezones.length - 1 && <ComboboxSeparator />}
</ComboboxGroup>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}Custom Items
You can render a custom component inside ComboboxItem.
"use client"
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from "@/components/ui/combobox"
import {
Item,
ItemContent,
ItemDescription,
ItemTitle,
} from "@/components/ui/item"
const countries = [
{ code: "", value: "", continent: "", label: "Select country" },
{
code: "ar",
value: "argentina",
label: "Argentina",
continent: "South America",
},
{ code: "au", value: "australia", label: "Australia", continent: "Oceania" },
{ code: "br", value: "brazil", label: "Brazil", continent: "South America" },
{ code: "ca", value: "canada", label: "Canada", continent: "North America" },
{ code: "cn", value: "china", label: "China", continent: "Asia" },
{
code: "co",
value: "colombia",
label: "Colombia",
continent: "South America",
},
{ code: "eg", value: "egypt", label: "Egypt", continent: "Africa" },
{ code: "fr", value: "france", label: "France", continent: "Europe" },
{ code: "de", value: "germany", label: "Germany", continent: "Europe" },
{ code: "it", value: "italy", label: "Italy", continent: "Europe" },
{ code: "jp", value: "japan", label: "Japan", continent: "Asia" },
{ code: "ke", value: "kenya", label: "Kenya", continent: "Africa" },
{ code: "mx", value: "mexico", label: "Mexico", continent: "North America" },
{
code: "nz",
value: "new-zealand",
label: "New Zealand",
continent: "Oceania",
},
{ code: "ng", value: "nigeria", label: "Nigeria", continent: "Africa" },
{
code: "za",
value: "south-africa",
label: "South Africa",
continent: "Africa",
},
{ code: "kr", value: "south-korea", label: "South Korea", continent: "Asia" },
{
code: "gb",
value: "united-kingdom",
label: "United Kingdom",
continent: "Europe",
},
{
code: "us",
value: "united-states",
label: "United States",
continent: "North America",
},
]
export function ComboboxWithCustomItems() {
return (
<Combobox
items={countries.filter((country) => country.code !== "")}
itemToStringValue={(country: (typeof countries)[number]) => country.label}
>
<ComboboxInput placeholder="Search countries..." />
<ComboboxContent>
<ComboboxEmpty>No countries found.</ComboboxEmpty>
<ComboboxList>
{(country) => (
<ComboboxItem key={country.code} value={country}>
<Item size="xs" className="p-0">
<ItemContent>
<ItemTitle className="whitespace-nowrap">
{country.label}
</ItemTitle>
<ItemDescription>
{country.continent} ({country.code})
</ItemDescription>
</ItemContent>
</Item>
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}Invalid
Use the aria-invalid prop to make the combobox invalid.
"use client"
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from "@/components/ui/combobox"
const frameworks = [
"Next.js",
"SvelteKit",
"Nuxt.js",
"Remix",
"Astro",
] as const
export function ComboboxInvalid() {
return (
<Combobox items={frameworks}>
<ComboboxInput placeholder="Select a framework" aria-invalid="true" />
<ComboboxContent>
<ComboboxEmpty>No items found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item} value={item}>
{item}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}Disabled
Use the disabled prop to disable the combobox.
"use client"
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from "@/components/ui/combobox"
const frameworks = [
"Next.js",
"SvelteKit",
"Nuxt.js",
"Remix",
"Astro",
] as const
export function ComboboxDisabled() {
return (
<Combobox items={frameworks}>
<ComboboxInput placeholder="Select a framework" disabled />
<ComboboxContent>
<ComboboxEmpty>No items found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item} value={item}>
{item}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}Auto Highlight
Use the autoHighlight prop to automatically highlight the first item on filter.
"use client"
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from "@/components/ui/combobox"
const frameworks = [
"Next.js",
"SvelteKit",
"Nuxt.js",
"Remix",
"Astro",
] as const
export function ComboboxAutoHighlight() {
return (
<Combobox items={frameworks} autoHighlight>
<ComboboxInput placeholder="Select a framework" />
<ComboboxContent>
<ComboboxEmpty>No items found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item} value={item}>
{item}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}Popup
You can trigger the combobox from a button or any other component by using the render prop.
"use client"
import { Button } from "@/components/ui/button"
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
ComboboxTrigger,
ComboboxValue,
} from "@/components/ui/combobox"
const countries = [
{ code: "", value: "", continent: "", label: "Select country" },
{
code: "ar",
value: "argentina",
label: "Argentina",
continent: "South America",
},
{ code: "au", value: "australia", label: "Australia", continent: "Oceania" },
{ code: "br", value: "brazil", label: "Brazil", continent: "South America" },
{ code: "ca", value: "canada", label: "Canada", continent: "North America" },
{ code: "cn", value: "china", label: "China", continent: "Asia" },
{
code: "co",
value: "colombia",
label: "Colombia",
continent: "South America",
},
{ code: "eg", value: "egypt", label: "Egypt", continent: "Africa" },
{ code: "fr", value: "france", label: "France", continent: "Europe" },
{ code: "de", value: "germany", label: "Germany", continent: "Europe" },
{ code: "it", value: "italy", label: "Italy", continent: "Europe" },
{ code: "jp", value: "japan", label: "Japan", continent: "Asia" },
{ code: "ke", value: "kenya", label: "Kenya", continent: "Africa" },
{ code: "mx", value: "mexico", label: "Mexico", continent: "North America" },
{
code: "nz",
value: "new-zealand",
label: "New Zealand",
continent: "Oceania",
},
{ code: "ng", value: "nigeria", label: "Nigeria", continent: "Africa" },
{
code: "za",
value: "south-africa",
label: "South Africa",
continent: "Africa",
},
{ code: "kr", value: "south-korea", label: "South Korea", continent: "Asia" },
{
code: "gb",
value: "united-kingdom",
label: "United Kingdom",
continent: "Europe",
},
{
code: "us",
value: "united-states",
label: "United States",
continent: "North America",
},
]
export function ComboboxPopup() {
return (
<>
<Combobox items={countries} defaultValue={countries[0]}>
<ComboboxTrigger
render={
<Button
variant="outline"
className="w-64 justify-between font-normal"
/>
}
>
<ComboboxValue />
</ComboboxTrigger>
<ComboboxContent>
<ComboboxInput showTrigger={false} placeholder="Search" />
<ComboboxEmpty>No items found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.code} value={item}>
{item.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
</>
)
}Input Group
You can add an addon to the combobox by using the InputGroupAddon component inside the ComboboxInput.
"use client"
import { GlobeIcon } from "lucide-react"
import {
Combobox,
ComboboxCollection,
ComboboxContent,
ComboboxEmpty,
ComboboxGroup,
ComboboxInput,
ComboboxItem,
ComboboxLabel,
ComboboxList,
} from "@/components/ui/combobox"
import { InputGroupAddon } from "@/components/ui/input-group"
const timezones = [
{
value: "Americas",
items: [
"(GMT-5) New York",
"(GMT-8) Los Angeles",
"(GMT-6) Chicago",
"(GMT-5) Toronto",
"(GMT-8) Vancouver",
"(GMT-3) São Paulo",
],
},
{
value: "Europe",
items: [
"(GMT+0) London",
"(GMT+1) Paris",
"(GMT+1) Berlin",
"(GMT+1) Rome",
"(GMT+1) Madrid",
"(GMT+1) Amsterdam",
],
},
{
value: "Asia/Pacific",
items: [
"(GMT+9) Tokyo",
"(GMT+8) Shanghai",
"(GMT+8) Singapore",
"(GMT+4) Dubai",
"(GMT+11) Sydney",
"(GMT+9) Seoul",
],
},
] as const
export function ComboxboxInputGroup() {
return (
<Combobox items={timezones}>
<ComboboxInput placeholder="Select a timezone">
<InputGroupAddon>
<GlobeIcon />
</InputGroupAddon>
</ComboboxInput>
<ComboboxContent alignOffset={-28} className="w-60">
<ComboboxEmpty>No timezones found.</ComboboxEmpty>
<ComboboxList>
{(group) => (
<ComboboxGroup key={group.value} items={group.items}>
<ComboboxLabel>{group.value}</ComboboxLabel>
<ComboboxCollection>
{(item) => (
<ComboboxItem key={item} value={item}>
{item}
</ComboboxItem>
)}
</ComboboxCollection>
</ComboboxGroup>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}RTL
To enable RTL support in shadcn/ui, see the RTL configuration guide.
"use client"
import * as React from "react"
import {
Combobox,
ComboboxChip,
ComboboxChips,
ComboboxChipsInput,
ComboboxContent,
ComboboxEmpty,
ComboboxItem,
ComboboxList,
ComboboxValue,
useComboboxAnchor,
} from "@/components/ui/combobox"
import { Field, FieldLabel } from "@/components/ui/field"
import {
useTranslation,
type Translations,
} from "@/components/language-selector"
const categories = [
"technology",
"design",
"business",
"marketing",
"education",
"health",
] as const
const translations: Translations = {
en: {
dir: "ltr",
values: {
label: "Categories",
placeholder: "Add categories",
empty: "No categories found.",
technology: "Technology",
design: "Design",
business: "Business",
marketing: "Marketing",
education: "Education",
health: "Health",
},
},
ar: {
dir: "rtl",
values: {
label: "الفئات",
placeholder: "أضف فئات",
empty: "لم يتم العثور على فئات.",
technology: "التكنولوجيا",
design: "التصميم",
business: "الأعمال",
marketing: "التسويق",
education: "التعليم",
health: "الصحة",
},
},
he: {
dir: "rtl",
values: {
label: "קטגוריות",
placeholder: "הוסף קטגוריות",
empty: "לא נמצאו קטגוריות.",
technology: "טכנולוגיה",
design: "עיצוב",
business: "עסקים",
marketing: "שיווק",
education: "חינוך",
health: "בריאות",
},
},
}
export function ComboboxRtl() {
const { dir, t, language } = useTranslation(translations, "ar")
const anchor = useComboboxAnchor()
const categoryLabels: Record<string, string> = {
technology: t.technology,
design: t.design,
business: t.business,
marketing: t.marketing,
education: t.education,
health: t.health,
}
return (
<Field className="mx-auto w-full max-w-xs">
<FieldLabel>{t.label}</FieldLabel>
<Combobox
multiple
autoHighlight
items={categories}
defaultValue={[categories[0]]}
itemToStringValue={(item: (typeof categories)[number]) =>
categoryLabels[item] || item
}
>
<ComboboxChips ref={anchor}>
<ComboboxValue>
{(values) => (
<React.Fragment>
{values.map((value: string) => (
<ComboboxChip key={value}>
{categoryLabels[value] || value}
</ComboboxChip>
))}
<ComboboxChipsInput placeholder={t.placeholder} />
</React.Fragment>
)}
</ComboboxValue>
</ComboboxChips>
<ComboboxContent
anchor={anchor}
dir={dir}
data-lang={dir === "rtl" ? language : undefined}
>
<ComboboxEmpty>{t.empty}</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item} value={item}>
{categoryLabels[item] || item}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
</Field>
)
}API Reference
Source: react/src/components/ui/combobox.tsx
See the Base UI documentation for more information.