The Select component provides a dropdown menu for selecting from a list of options with support for groups, multiple selections, and custom alignment.
Installation
npx shadcn@latest add @eo-n/select
Install dependencies
Install the required packages:npm install @base-ui/react lucide-react
Copy component code
Copy and paste the select component code into your project at components/ui/select.tsx.
Update imports
Update the import paths to match your project setup.
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
export default function Example() {
const items = [
{ label: "Apple", value: "apple" },
{ label: "Banana", value: "banana" },
{ label: "Cherry", value: "cherry" },
];
return (
<Select items={items}>
<SelectTrigger>
<SelectValue placeholder="Select a fruit" />
</SelectTrigger>
<SelectContent>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectContent>
</Select>
);
}
Examples
Default
const items = [
{ label: "Select theme", value: null },
{ label: "System default", value: "system" },
{ label: "Light", value: "light" },
{ label: "Dark", value: "dark" },
];
<Select items={items}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectContent>
</Select>
With Groups
import { SelectGroup, SelectGroupLabel } from "@/components/ui/select";
<Select items={items}>
<SelectTrigger>
<SelectValue placeholder="Select a fruit" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectGroupLabel>Fruits</SelectGroupLabel>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
<SelectItem value="cherry">Cherry</SelectItem>
</SelectGroup>
<SelectGroup>
<SelectGroupLabel>Vegetables</SelectGroupLabel>
<SelectItem value="carrot">Carrot</SelectItem>
<SelectItem value="lettuce">Lettuce</SelectItem>
<SelectItem value="tomato">Tomato</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
Align Trigger
Align the popup width with the trigger element.
<Select items={items}>
<SelectTrigger>
<SelectValue placeholder="Select..." />
</SelectTrigger>
<SelectContent alignItemWithTrigger>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectContent>
</Select>
Multiple Selection
<Select items={items} multiple>
<SelectTrigger>
<SelectValue placeholder="Select multiple" />
</SelectTrigger>
<SelectContent>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectContent>
</Select>
Small Size
<Select items={items}>
<SelectTrigger size="sm">
<SelectValue placeholder="Small select" />
</SelectTrigger>
<SelectContent>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectContent>
</Select>
With Icons
import { Moon, Sun, Monitor } from "lucide-react";
<Select items={items}>
<SelectTrigger>
<SelectValue placeholder="Select theme" />
</SelectTrigger>
<SelectContent>
<SelectItem value="light">
<Sun />
Light
</SelectItem>
<SelectItem value="dark">
<Moon />
Dark
</SelectItem>
<SelectItem value="system">
<Monitor />
System
</SelectItem>
</SelectContent>
</Select>
Controlled
import { useState } from "react";
function ControlledSelect() {
const [value, setValue] = useState("apple");
return (
<Select items={items} value={value} onValueChange={setValue}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectContent>
</Select>
);
}
API Reference
Extends all props from @base-ui/react Select.Root component.
Array of items for the select. Each item should have a label and value.
The controlled selected value(s).
The default selected value(s) when uncontrolled.
Callback fired when the selected value changes.(value: string | string[]) => void
Whether multiple items can be selected.
Whether the select is disabled.
Whether the select is required in a form.
The name attribute for form submission.
SelectTrigger
The size of the trigger button.Options: default | sm
Additional CSS classes to apply.
SelectValue
Placeholder text when no value is selected.
Additional CSS classes to apply.
SelectContent
The distance in pixels from the trigger.
Whether to align the selected item with the trigger.
Additional CSS classes to apply.
SelectItem
Whether the item is disabled.
Additional CSS classes to apply.
SelectGroup
Groups related select items together.
SelectGroupLabel
Additional CSS classes to apply.
SelectSeparator
Visual separator between select items.
Additional CSS classes to apply.
TypeScript
import { Select as SelectPrimitive } from "@base-ui/react";
const Select = SelectPrimitive.Root;
interface SelectTriggerProps
extends React.ComponentProps<typeof SelectPrimitive.Trigger> {
size?: "sm" | "default";
}
type SelectItemProps = React.ComponentProps<typeof SelectPrimitive.Item>;
Accessibility
- Fully keyboard accessible (Arrow keys, Enter, Escape)
- Proper ARIA attributes
- Focus management
- Scrollable with scroll indicators
- Works with form labels
- Screen reader support
Related