"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 ComboboxDemo() { 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> );}pnpm dlx shadcn@latest add @herocn/comboboximport { Combobox, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList,} from "@/components/ui/combobox"Pass an items array to Combobox and render items inside ComboboxList using the render prop.
const frameworks = ["Next.js", "SvelteKit", "Nuxt.js", "Remix", "Astro"]
<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>Use the following composition to build a Combobox:
Combobox├── ComboboxInput└── ComboboxContent ├── ComboboxEmpty └── ComboboxList ├── ComboboxItem └── ComboboxItemMulti-select with multiple, chips, and a chips input.
Combobox├── ComboboxChips│ ├── ComboboxValue│ │ └── ComboboxChip│ └── ComboboxChipsInput└── ComboboxContent ├── ComboboxEmpty └── ComboboxList ├── ComboboxItem └── ComboboxItemNested items per group using ComboboxCollection inside each ComboboxGroup, with a separator between groups.
Combobox├── ComboboxInput└── ComboboxContent ├── ComboboxEmpty └── ComboboxList ├── ComboboxGroup │ ├── ComboboxLabel │ └── ComboboxCollection │ ├── ComboboxItem │ └── ComboboxItem ├── ComboboxSeparator └── ComboboxGroup ├── ComboboxLabel └── ComboboxCollection ├── ComboboxItem └── ComboboxItemUse multiple, ComboboxChips, ComboboxChip, and ComboboxChipsInput for multi-select.
"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> );}Use ComboboxGroup, ComboboxLabel, ComboboxCollection, and ComboboxSeparator to organize 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 ComboboxGroups() { 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> );}Set showClear on ComboboxInput 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 ComboboxClear() { 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> );}Set disabled on ComboboxInput to disable the control.
"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> );}Set aria-invalid="true" on ComboboxInput to show an error state.
"use client";import { Combobox, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList,} from "@/components/ui/combobox";import { Field, FieldError, FieldLabel } from "@/components/ui/field";
const frameworks = [ "Next.js", "SvelteKit", "Nuxt.js", "Remix", "Astro",] as const;
export function ComboboxInvalid() { return ( <Field data-invalid className="w-full max-w-48"> <FieldLabel>Framework</FieldLabel> <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> <FieldError>Please select a framework.</FieldError> </Field> );}Set autoHighlight on the root Combobox 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> );}Use ComboboxTrigger and ComboboxValue to trigger the combobox from a button. Move ComboboxInput inside ComboboxContent.
"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="tertiary" className="w-64 justify-between font-normal" > <ComboboxValue /> </Button> } /> <ComboboxContent className="min-w-(--anchor-width)"> <ComboboxInput variant="secondary" showTrigger={false} placeholder="Search" /> <ComboboxEmpty>No items found.</ComboboxEmpty> <ComboboxList> {(item) => ( <ComboboxItem key={item.code} value={item}> {item.label} </ComboboxItem> )} </ComboboxList> </ComboboxContent> </Combobox> );}The Combobox component supports two visual variants:
default (default) — Standard styling, suitable for most use casessecondary — Lower emphasis variant, suitable for use in Surface components"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 ComboboxVariants() { return ( <div className="flex w-full max-w-sm flex-col gap-4"> <Combobox items={frameworks}> <ComboboxInput placeholder="Default" /> <ComboboxContent> <ComboboxEmpty>No items found.</ComboboxEmpty> <ComboboxList> {(item) => ( <ComboboxItem key={item} value={item}> {item} </ComboboxItem> )} </ComboboxList> </ComboboxContent> </Combobox> <Combobox items={frameworks} variant="secondary"> <ComboboxInput placeholder="Secondary" /> <ComboboxContent> <ComboboxEmpty>No items found.</ComboboxEmpty> <ComboboxList> {(item) => ( <ComboboxItem key={item} value={item}> {item} </ComboboxItem> )} </ComboboxList> </ComboboxContent> </Combobox> </div> );}Place the combobox inside a Surface panel. Use variant="secondary" on Combobox so the input sits cleanly on the surface background.
Select your preferred framework.
"use client";import { Combobox, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList,} from "@/components/ui/combobox";import { Surface } from "@/components/ui/surface";
const frameworks = ["Next.js", "SvelteKit", "Nuxt.js", "Remix", "Astro"];
export function ComboboxSurface() { return ( <Surface className="w-full max-w-sm rounded-3xl border p-4"> <h4 className="font-medium text-sm">Framework</h4> <p className="mt-1 text-muted-foreground text-sm"> Select your preferred framework. </p> <div className="mt-4"> <Combobox items={frameworks} variant="secondary"> <ComboboxInput placeholder="Select a framework" /> <ComboboxContent> <ComboboxEmpty>No items found.</ComboboxEmpty> <ComboboxList> {(item) => ( <ComboboxItem key={item} value={item}> {item} </ComboboxItem> )} </ComboboxList> </ComboboxContent> </Combobox> </div> </Surface> );}To enable RTL support in shadcn/ui, see the RTL configuration guide.
"use client";
import * as React from "react";
import { type Translations, useTranslation,} from "@/components/language-selector";import { Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, ComboboxContent, ComboboxEmpty, ComboboxItem, ComboboxList, ComboboxValue, useComboboxAnchor,} from "@/components/ui/combobox";import { Field, FieldLabel } from "@/components/ui/field";
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 dir={dir} data-lang={dir === "rtl" ? language : undefined} 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> );}The combobox is built on Base UI Combobox. Combobox forwards props to the root; sub-components forward to their corresponding Base UI primitives.
| Prop | Type | Default |
|---|---|---|
| variant | "default" | "secondary" | "default" |
Sets the input style via context (secondary uses a softer background). | ||
| Prop | Type | Default |
|---|---|---|
| showTrigger | boolean | true |
Shows the dropdown trigger chevron button. | ||
| showClear | boolean | false |
Shows a clear button to reset the value. | ||
| variant | "default" | "secondary" | - |
Overrides the context variant for this input. | ||
| Prop | Type | Default |
|---|---|---|
| showRemove | boolean | true |
Shows the remove button on the chip. | ||
See the Base UI Combobox API reference for all other props (items, value, onValueChange, multiple, autoHighlight, positioning, etc.).