Shadcn Select
The shadcn/ui Select lets users pick one option from a list, styled with Tailwind CSS v4. It replaces the native select with an accessible, keyboard-navigable menu that supports groups, labels, and a placeholder. Selects appear in checkout, contact, and filter flows across ShadcnStore blocks.
Key features
- Accessible, keyboard-navigable single-choice menu with type-ahead.
- Groups, labels, and a placeholder value.
itemson the root maps values to labels forSelectValuedisplay.- Controlled or uncontrolled via
value/defaultValue. - Renders in a portal to avoid clipping inside dialogs and cards.
alignItemWithTriggeronSelectContentaligns the highlighted item with the trigger.
Installation
npx shadcn@latest add selectUsage
Pass items on the Select root so SelectValue shows the option label (e.g. "Apple") instead of the raw value (e.g. "apple").
import {
Select,
SelectTrigger,
SelectValue,
SelectContent,
SelectItem,
SelectGroup,
SelectLabel,
} from "@/components/ui/select"
const fruits = [
{ label: "Apple", value: "apple" },
{ label: "Banana", value: "banana" },
]
export function Example() {
return (
<Select items={fruits}>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Select a fruit" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Fruits</SelectLabel>
{fruits.map((fruit) => (
<SelectItem key={fruit.value} value={fruit.value}>
{fruit.label}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
)
}Grouped options
const fruits = [
{ label: "Apple", value: "apple" },
{ label: "Banana", value: "banana" },
{ label: "Blueberry", value: "blueberry" },
{ label: "Grapes", value: "grapes" },
]
<Select items={fruits}>
<SelectTrigger className="w-[200px]">
<SelectValue placeholder="Select a fruit" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Fruits</SelectLabel>
{fruits.map((fruit) => (
<SelectItem key={fruit.value} value={fruit.value}>
{fruit.label}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>Controlled value
const fruits = [
{ label: "Apple", value: "apple" },
{ label: "Banana", value: "banana" },
]
const [value, setValue] = useState("")
<Select items={fruits} value={value} onValueChange={setValue}>
…
</Select>Scrollable
With a long list of options, the content area scrolls and keeps scroll buttons at the edges. No extra configuration is needed.
const timezoneItems = timezones.map((tz) => ({ label: tz, value: tz }))
<Select items={timezoneItems}>
<SelectTrigger>…</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Timezone</SelectLabel>
{timezoneItems.map((tz) => (
<SelectItem key={tz.value} value={tz.value}>{tz.label}</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>Disabled
Disable the whole control with disabled on Select, or a single option with disabled on SelectItem.
const fruits = [
{ label: "Apple", value: "apple" },
{ label: "Banana", value: "banana" },
]
<Select items={fruits} disabled>…</Select>
<SelectItem value="banana" disabled>Banana (out of stock)</SelectItem>Positioning
SelectContent accepts alignItemWithTrigger (defaults to true) so the highlighted option lines up with the trigger when the menu opens. Set it to false if you prefer the menu to open from the top of the list.
<SelectContent alignItemWithTrigger={false}>…</SelectContent>Accessibility
- The trigger exposes the current value; always provide a
SelectValuewith aplaceholderso an empty select still has a readable state. - Pass
itemson the root so the displayed label matches what users see in the list. - The menu is fully keyboard-operable: open with Enter or Space, move with arrow keys, and type-ahead jumps to matching options.
- Pair the trigger with a Label in forms so the control has an accessible name.
When to use the Select
Use a Select when the user picks one value from a short, known list: country, currency, status, or category. For long lists or when users know what they want and would rather type, use a Combobox with search. For a handful of visible options, a Radio Group may read better than a Select, and for multiple choices use Checkboxes or a multi-select.
Used in these blocks
- Checkout forms: country and shipping selectors.
- Contact: subject and department selects.
- Category filters: sort and filter selects.
Related components
A Select sits inside a Form beside Input fields, and often within a Dialog or Card. For grouped action menus rather than value selection, use a Dropdown Menu.
FAQ
What is the shadcn select used for?
The Select lets users pick one option from a list, such as a country, currency, or category. It replaces the native select with a styled, accessible menu.
What is the difference between Select and Combobox?
Select is for choosing from a short, fixed list. Combobox adds type-to-filter search and suits long or async option sets.
How do I control the selected value?
Pass value and onValueChange to the Select root, or use defaultValue for an uncontrolled starting value. Always pass items so the trigger shows the correct label.
Why is my Select content clipped inside a dialog?
The content renders in a portal by default, which avoids clipping. If you changed that, ensure the container does not have overflow: hidden around the trigger.
Why does SelectValue show the raw value instead of the label?
Pass items on the Select root with label and value for each option. Without items, SelectValue displays the raw value string.