← Back to Design System
Select
Advanced select component with icons, avatars, custom content, groups, scrollable items, and form integration.
Basic Select
<Select
items={[
{ id: "apple", label: "Apple" },
{ id: "orange", label: "Orange" },
{ id: "banana", label: "Banana" }
]}
placeholder="Select a fruit"
/>Disabled Select
<Select
disabled
items={basicItems}
placeholder="Select a fruit"
/>Select with Icons and Supporting Text
<Select
items={[
{
id: "user",
label: "User",
icon: <User01 className="w-4 h-4" />,
supportingText: "Limited access",
},
{
id: "admin",
label: "Administrator",
icon: <Shield01 className="w-4 h-4" />,
supportingText: "Full access",
},
{
id: "moderator",
label: "Moderator",
icon: <Star01 className="w-4 h-4" />,
supportingText: "Content management",
},
]}
placeholder="Select a role"
/>Select with Avatars
<Select
items={[
{
id: "john",
label: "John Doe",
value: "john",
avatarUrl: "/images/avatar-1.png",
supportingText: "john@example.com",
},
{
id: "jane",
value: "jane",
label: "Jane Smith",
avatarUrl: "/images/avatar-2.png",
supportingText: "jane@example.com",
},
]}
placeholder="Select a user"
/>Custom Item Rendering
<Select
items={[
{
id: "file1",
label: "Important Document.pdf",
icon: <File01 className="w-4 h-4" />,
supportingText: "Modified 2 hours ago",
},
{
id: "file2",
label: "Presentation.pptx",
icon: <File01 className="w-4 h-4" />,
supportingText: "Modified yesterday",
},
]}
placeholder="Select a file"
renderItem={(item) => (
<div className="flex items-center justify-between w-full">
<div className="flex items-center gap-2">
{item.icon}
<span>{item.label}</span>
</div>
<span className="text-xs text-tertiary">
{item.supportingText}
</span>
</div>
)}
/>Mixed Content with Groups and Separators
<Select
items={[
{
id: "docs",
type: "group",
label: "Recent Files",
items: [
{
id: "doc1",
label: "Report.pdf",
icon: <File01 className="w-4 h-4" />,
supportingText: "2.4 MB",
},
],
},
{ id: "sep1", type: "separator" },
{
id: "projects-group",
type: "group",
label: "Projects",
items: [
{
id: "proj1",
label: "Project Alpha",
supportingText: "Active",
icon: <Star01 className="w-4 h-4" />,
},
{
id: "proj2",
label: "Project Beta",
supportingText: "On hold",
},
],
},
]}
placeholder="Select an item"
triggerClassName="w-[360px]"
/>Scrollable Select With Disabled Item
<Select
items={[
{
id: "north-america",
type: "group",
label: "North America",
items: [
{ id: "est", label: "Eastern Standard Time (EST)" },
{ id: "cst", label: "Central Standard Time (CST)", disabled: true },
{ id: "mst", label: "Mountain Standard Time (MST)" },
{ id: "pst", label: "Pacific Standard Time (PST)" },
{ id: "akst", label: "Alaska Standard Time (AKST)" },
{ id: "hst", label: "Hawaii Standard Time (HST)" },
],
},
{
id: "europe-africa",
type: "group",
label: "Europe & Africa",
items: [
{ id: "gmt", label: "Greenwich Mean Time (GMT)" },
{ id: "cet", label: "Central European Time (CET)" },
{ id: "eet", label: "Eastern European Time (EET)" },
{ id: "west", label: "Western European Summer Time (WEST)" },
{ id: "cat", label: "Central Africa Time (CAT)" },
{ id: "eat", label: "East Africa Time (EAT)" },
],
},
]}
placeholder="Select a timezone"
triggerClassName="w-[360px]"
/>Combobox
<Combobox
placeholder="Search priority..."
items={priorities}
value={priority}
onValueChange={setPriority}
size="md"
/>MultiSelect
<MultiSelect
placeholder="Search"
items={avatarItems}
value={userValues}
onValueChange={setUserValues}
size="sm"
/>Select in Form
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
const formSchema = z.object({
email: z.email({
message: "Please select an email to display.",
}),
framework: z.string({
message: "Please select a framework.",
}),
users: z.array(z.string()).min(1, "Please select at least one user."),
});
function onSubmit(data: z.infer<typeof formSchema>) {
toast("You submitted the following values", {
description: (
<pre className="mt-2 w-[320px] rounded-md bg-neutral-950 p-4">
<code className="text-white">{JSON.stringify(data, null, 2)}</code>
</pre>
),
});
}
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
<SelectForm
control={form.control}
name="email"
label="Email"
labelTooltip="This is a tooltip"
placeholder="Select a verified email to display"
items={emailItems}
isRequired
/>
<ComboboxForm
control={form.control}
name="framework"
label="Framework"
labelTooltip="This is a tooltip"
placeholder="Select a framework"
items={frameworks}
isRequired
/>
<MultiSelectForm
control={form.control}
name="users"
label="Users"
labelTooltip="This is a tooltip"
placeholder="Select some users"
items={avatarItems}
isRequired
/>
<Button type="submit">Submit</Button>
</form>
</Form>API Reference
Select Props
| Props | Type | Default | Description |
|---|---|---|---|
| items | SelectItemData[] | [] | List of items to display in the select (items, groups, labels, separators) |
| value? | string | — | Selected value (controlled) |
| onValueChange? | (value: string) => void | — | Callback called when value changes |
| placeholder? | string | "Select an option..." | Text displayed when no value is selected |
| size? | "sm" | "default" | "default" | Size of the trigger |
| disabled? | boolean | false | Disables the select |
| showIcon? | boolean | false | Show icon in the trigger for selected item |
| showAvatar? | boolean | false | Show avatar in the trigger for selected item |
| renderItem? | (item: SelectItemData) => ReactNode | — | Custom render function for items |
| triggerClassName? | string | — | Custom class for the trigger |
| contentClassName? | string | — | Custom class for the content |
| itemClassName? | string | — | Custom class for items |
SelectItemData
| Props | Type | Default | Description |
|---|---|---|---|
id | string | — | Unique identifier for the item |
label? | React.ReactNode | — | Text or element displayed |
value? | string | — | Value used for selection (defaults to id) |
disabled? | boolean | false | Disables the item |
type? | "item" | "separator" | "group" | "item" | Type of element |
icon? | React.ReactNode | — | Icon to display |
avatarUrl? | string | — | Avatar image URL |
supportingText? | string | — | Secondary text displayed below label |
customContent? | React.ReactNode | — | Completely custom content for the item |
items? | SelectItemData[] | [] | Sub-items for groups |
Combobox and MutiSelect Props
| Props | Type | Default | Description |
|---|---|---|---|
| placeholder? | string | "Search" | Placeholder text displayed in the input field. |
| shortcut? | boolean | false | Whether to display the keyboard shortcut hint (⌘K). |
| size? | "sm" | "md" | "sm" | Controls the input size and spacing. |
| items? | ComboboxItemBase[] | [] | List of items available in the combobox. |
| value? | string | null | — | The controlled selected value. |
| onValueChange? | function: (value: string | null) => void | — | Callback fired when the selected value changes. |
| disabled? | boolean | false | Whether the combobox is disabled. |
| inputClassName? | string | — | Custom class applied to the input container. |
| shortcutClassName? | string | — | Custom class applied to the shortcut indicator. |
| contentClassName? | string | — | Custom class applied to the dropdown content. |
| emptyMessage? | string | "No results found." | Message displayed when no items match the search input. |
| children? | React.ReactNode | — | Optional custom rendering of items. If provided, it overrides items. |
SelectForm, ComboboxForm and MultiSelectForm Props
Extends all Select type props plus the following form-specific props:
| Props | Type | Default | Description |
|---|---|---|---|
control | Control | — | React Hook Form control object |
name | string | — | Field name |
label? | string | — | Field label |
description? | string | — | Field description |
isRequired? | boolean | false | Shows required indicator |