Get Started
Components
- Alert
- Avatar
- Badge
- Breadcrumb
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Checkbox Group
- ComboBox
- Command
- Data Table
- Date Field
- Date Picker
- Date Range Picker
- Dialog
- Disclosure
- Disclosure Group
- Drawer
- Empty
- Field
- File Trigger
- Form
- Grid List
- Hover Card
- Input
- Input Group
- Input OTP
- Item
- Kbd
- Label
- ListBox
- Menu
- Number Field
- Pagination
- Popover
- Progress Bar
- Radio Group
- Range Calendar
- Resizable
- Search Field
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Tag Group
- Text Field
- Textarea
- Time Field
- Toast
- Toggle Button
- Toggle Button Group
- Tooltip
- Tree
- Typography
AI Elements
A combo box combines a text input with a listbox, allowing users to filter a list of options to items matching a query.
"use client"
import { ComboBox, ComboBoxItem } from "@/components/ui/combobox"
const frameworks = [
{ id: "next.js", name: "Next.js" },
{ id: "sveltekit", name: "SvelteKit" },
{ id: "nuxt.js", name: "Nuxt.js" },
{ id: "remix", name: "Remix" },
{ id: "astro", name: "Astro" },
{ id: "vue", name: "Vue" },
{ id: "angular", name: "Angular" },
]
export function ComboboxDemo() {
return (
<ComboBox
label="Favorite Framework"
placeholder="Search framework..."
className="w-full max-w-xs"
>
{frameworks.map((framework) => (
<ComboBoxItem
key={framework.id}
id={framework.id}
textValue={framework.name}
>
{framework.name}
</ComboBoxItem>
))}
</ComboBox>
)
}
Installation
CLI
Manual
pnpmnpmyarnbunpnpm dlx shadcn@latest add combobox
Usage
import { ComboBox, ComboBoxItem } from "@/components/ui/combobox"<ComboBox
label="Favorite Framework"
placeholder="Search framework..."
className="w-full max-w-xs"
>
<ComboBoxItem id="next.js" textValue="Next.js">
Next.js
</ComboBoxItem>
<ComboBoxItem id="sveltekit" textValue="SvelteKit">
SvelteKit
</ComboBoxItem>
<ComboBoxItem id="nuxt.js" textValue="Nuxt.js">
Nuxt.js
</ComboBoxItem>
<ComboBoxItem id="remix" textValue="Remix">
Remix
</ComboBoxItem>
<ComboBoxItem id="astro" textValue="Astro">
Astro
</ComboBoxItem>
</ComboBox>Examples
With Sections
import {
ComboBox,
ComboBoxItem,
ComboBoxSection,
} from "@/components/ui/combobox"
export function ComboboxSections() {
return (
<ComboBox
label="Select Language"
placeholder="Search languages..."
className="w-full max-w-xs"
>
<ComboBoxSection title="Popular">
<ComboBoxItem id="js" textValue="JavaScript">
JavaScript
</ComboBoxItem>
<ComboBoxItem id="ts" textValue="TypeScript">
TypeScript
</ComboBoxItem>
<ComboBoxItem id="python" textValue="Python">
Python
</ComboBoxItem>
</ComboBoxSection>
<ComboBoxSection title="Web">
<ComboBoxItem id="html" textValue="HTML">
HTML
</ComboBoxItem>
<ComboBoxItem id="css" textValue="CSS">
CSS
</ComboBoxItem>
<ComboBoxItem id="php" textValue="PHP">
PHP
</ComboBoxItem>
</ComboBoxSection>
<ComboBoxSection title="Systems">
<ComboBoxItem id="rust" textValue="Rust">
Rust
</ComboBoxItem>
<ComboBoxItem id="go" textValue="Go">
Go
</ComboBoxItem>
<ComboBoxItem id="c" textValue="C">
C
</ComboBoxItem>
<ComboBoxItem id="cpp" textValue="C++">
C++
</ComboBoxItem>
</ComboBoxSection>
</ComboBox>
)
}
<ComboBox
label="Select Language"
placeholder="Search languages..."
className="w-full max-w-xs"
>
<ComboBoxSection title="Popular">
<ComboBoxItem id="js" textValue="JavaScript">
JavaScript
</ComboBoxItem>
<ComboBoxItem id="ts" textValue="TypeScript">
TypeScript
</ComboBoxItem>
</ComboBoxSection>
<ComboBoxSection title="Web">
<ComboBoxItem id="html" textValue="HTML">
HTML
</ComboBoxItem>
<ComboBoxItem id="css" textValue="CSS">
CSS
</ComboBoxItem>
</ComboBoxSection>
</ComboBox>Controlled
"use client"
import { useState } from "react"
import { ComboBox, ComboBoxItem } from "@/components/ui/combobox"
const countries = [
{ id: "us", name: "United States" },
{ id: "uk", name: "United Kingdom" },
{ id: "ca", name: "Canada" },
{ id: "au", name: "Australia" },
{ id: "de", name: "Germany" },
{ id: "fr", name: "France" },
{ id: "jp", name: "Japan" },
{ id: "in", name: "India" },
]
export function ComboboxControlled() {
const [selectedKey, setSelectedKey] = useState<string | null>(null)
return (
<div className="space-y-4">
<ComboBox
label="Select Country"
placeholder="Search countries..."
className="w-full max-w-xs"
selectedKey={selectedKey}
onSelectionChange={(key) => setSelectedKey(key as string)}
>
{countries.map((country) => (
<ComboBoxItem
key={country.id}
id={country.id}
textValue={country.name}
>
{country.name}
</ComboBoxItem>
))}
</ComboBox>
{selectedKey && (
<p className="text-muted-foreground text-sm">
Selected: {countries.find((c) => c.id === selectedKey)?.name}
</p>
)}
</div>
)
}
const [selectedKey, setSelectedKey] = useState<string | null>(null)
<ComboBox
label="Select Country"
placeholder="Search countries..."
selectedKey={selectedKey}
onSelectionChange={(key) => setSelectedKey(key as string)}
>
<ComboBoxItem id="us" textValue="United States">
United States
</ComboBoxItem>
<ComboBoxItem id="uk" textValue="United Kingdom">
United Kingdom
</ComboBoxItem>
<ComboBoxItem id="ca" textValue="Canada">
Canada
</ComboBoxItem>
</ComboBox>With Description
Choose your preferred code editor for development.
Choose your preferred code editor for development.
import { ComboBox, ComboBoxItem } from "@/components/ui/combobox"
const editors = [
{ id: "vscode", name: "Visual Studio Code" },
{ id: "sublime", name: "Sublime Text" },
{ id: "atom", name: "Atom" },
{ id: "vim", name: "Vim" },
{ id: "neovim", name: "Neovim" },
{ id: "emacs", name: "Emacs" },
]
export function ComboboxDescription() {
return (
<ComboBox
label="Code Editor"
description="Choose your preferred code editor for development."
placeholder="Search editors..."
className="w-full max-w-xs"
>
{editors.map((editor) => (
<ComboBoxItem key={editor.id} id={editor.id} textValue={editor.name}>
{editor.name}
</ComboBoxItem>
))}
</ComboBox>
)
}
<ComboBox
label="Code Editor"
description="Choose your preferred code editor for development."
placeholder="Search editors..."
>
<ComboBoxItem id="vscode" textValue="Visual Studio Code">
Visual Studio Code
</ComboBoxItem>
<ComboBoxItem id="sublime" textValue="Sublime Text">
Sublime Text
</ComboBoxItem>
<ComboBoxItem id="vim" textValue="Vim">
Vim
</ComboBoxItem>
</ComboBox>Disabled
import { ComboBox, ComboBoxItem } from "@/components/ui/combobox"
const options = [
{ id: "option1", name: "Option 1" },
{ id: "option2", name: "Option 2" },
{ id: "option3", name: "Option 3" },
]
export function ComboboxDisabled() {
return (
<ComboBox
label="Disabled ComboBox"
placeholder="Cannot interact..."
className="w-full max-w-xs"
isDisabled
>
{options.map((option) => (
<ComboBoxItem key={option.id} id={option.id} textValue={option.name}>
{option.name}
</ComboBoxItem>
))}
</ComboBox>
)
}
<ComboBox
label="Disabled ComboBox"
placeholder="Cannot interact..."
isDisabled
>
<ComboBoxItem id="option1">Option 1</ComboBoxItem>
<ComboBoxItem id="option2">Option 2</ComboBoxItem>
</ComboBox>Validation
"use client"
import { ComboBox, ComboBoxItem } from "@/components/ui/combobox"
const priorities = [
{ id: "low", name: "Low" },
{ id: "medium", name: "Medium" },
{ id: "high", name: "High" },
{ id: "urgent", name: "Urgent" },
]
export function ComboboxValidation() {
return (
<ComboBox
label="Priority"
placeholder="Select priority..."
className="w-full max-w-xs"
isRequired
errorMessage="Please select a priority level."
>
{priorities.map((priority) => (
<ComboBoxItem
key={priority.id}
id={priority.id}
textValue={priority.name}
>
{priority.name}
</ComboBoxItem>
))}
</ComboBox>
)
}
<ComboBox
label="Priority"
placeholder="Select priority..."
isRequired
errorMessage="Please select a priority level."
>
<ComboBoxItem id="low">Low</ComboBoxItem>
<ComboBoxItem id="medium">Medium</ComboBoxItem>
<ComboBoxItem id="high">High</ComboBoxItem>
</ComboBox>API Reference
ComboBox
The ComboBox component combines a text input with a listbox, providing autocomplete and filtering functionality.
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | - | Label text for the combobox |
placeholder | string | - | Placeholder text for the input |
description | string | - | Help text displayed below the combobox |
errorMessage | string | ((validation: ValidationResult) => string) | - | Error message for validation |
isDisabled | boolean | false | Whether the combobox is disabled |
isRequired | boolean | false | Whether the combobox is required |
size | "default" | "sm" | "default" | Size variant of the combobox |
selectedKey | string | null | - | Controlled selected key |
defaultSelectedKey | string | null | - | Default selected key (uncontrolled) |
onSelectionChange | (key: string | null) => void | - | Callback when selection changes |
items | Iterable<T> | - | Collection of items for dynamic rendering |
ComboBoxItem
The ComboBoxItem component represents an option in the combobox list.
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | - | Unique identifier for the item |
textValue | string | - | Text value used for filtering/searching |
isDisabled | boolean | false | Whether the item is disabled |
ComboBoxSection
The ComboBoxSection component groups related items together.
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | - | Section header text |
items | Iterable<T> | - | Collection of items in the section |
Features
- Autocomplete: Filter options as you type
- Keyboard Navigation: Full keyboard support with arrow keys and Enter
- Accessibility: Built on react-aria with ARIA best practices
- Custom Values: Support for user-entered custom values (when enabled)
- Sections: Organize options into labeled groups
- Validation: Built-in support for required fields and error messages
- Responsive: Works on mobile and desktop devices