Select
Choose one from a list of options.
Preview
Code
import {
Select, SelectContent, SelectItem, SelectTrigger, SelectValue,
} from "@/components/ui/select";
export function Example() {
return (
<Select>
<SelectTrigger>
<SelectValue placeholder="Select severity" />
</SelectTrigger>
<SelectContent>
<SelectItem value="Critical">Critical</SelectItem>
<SelectItem value="High">High</SelectItem>
<SelectItem value="Medium">Medium</SelectItem>
<SelectItem value="Low">Low</SelectItem>
</SelectContent>
</Select>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | — | Controlled selected value. |
| defaultValue | string | — | Uncontrolled initial value. |
| onValueChange | (value: string) => void | — | Called when the selection changes. |
| disabled | boolean | false | Disables the trigger. |
Sub-components
SelectTrigger— The visible button that opens the popup.| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | — | Additional Tailwind classes, merged with the component's defaults via cn(). |
SelectValue— Renders the currently selected value inside the trigger.| Prop | Type | Default | Description |
|---|---|---|---|
| placeholder | ReactNode | — | Shown when no value is selected. |
SelectContent— The popup list of items. Portals to document body.| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | — | Additional Tailwind classes, merged with the component's defaults via cn(). |
SelectItem— An individual option.| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | — | The value this item represents. |
| disabled | boolean | false | Disables this item. |
| className | string | — | Additional Tailwind classes, merged with the component's defaults via cn(). |
Built on Base UI Select. Keyboard: arrows navigate, Enter selects, type to search, Escape closes.
All components also accept standard HTML attributes for their root element (e.g. `id`, `aria-*`, `data-*`, event handlers) and forward `ref` where applicable.
Source
The full implementation of components/ui/select.tsx is below — copy it into your project and own it. Some components import the cn helper from lib/utils or other primitives; copy those too.
"use client";
import { cn } from "@/lib/utils";
import { Select as BaseSelect } from "@base-ui-components/react/select";
import { Check, ChevronDown } from "lucide-react";
import type { ComponentPropsWithoutRef, ReactNode } from "react";
export const Select = BaseSelect.Root;
export function SelectValue({
placeholder,
className,
...props
}: Omit<ComponentPropsWithoutRef<typeof BaseSelect.Value>, "children"> & {
placeholder?: ReactNode;
}) {
return (
<BaseSelect.Value className={cn("data-[placeholder]:text-fg-subtle", className)} {...props}>
{(value) => (value == null || value === "" ? placeholder : (value as ReactNode))}
</BaseSelect.Value>
);
}
export function SelectTrigger({
className,
children,
...props
}: ComponentPropsWithoutRef<typeof BaseSelect.Trigger>) {
return (
<BaseSelect.Trigger
className={cn(
"flex h-9 w-full items-center justify-between rounded-md border border-border bg-surface px-3 py-1 text-sm shadow-sm",
"focus-visible:outline-1 focus-visible:outline-offset-0 focus-visible:outline-accent",
"disabled:cursor-not-allowed disabled:opacity-50",
"data-[placeholder]:text-fg-subtle",
className,
)}
{...props}
>
{children}
<BaseSelect.Icon className="text-fg-muted">
<ChevronDown className="h-4 w-4" />
</BaseSelect.Icon>
</BaseSelect.Trigger>
);
}
export function SelectContent({
className,
children,
...props
}: ComponentPropsWithoutRef<typeof BaseSelect.Popup> & { children?: ReactNode }) {
return (
<BaseSelect.Portal>
<BaseSelect.Positioner sideOffset={4} alignItemWithTrigger={false} align="start">
<BaseSelect.Popup
className={cn(
"z-50 max-h-[var(--available-height)] min-w-[var(--anchor-width)] overflow-y-auto",
"rounded-md border border-border bg-surface-elevated p-1 shadow-md",
"data-[starting-style]:opacity-0 data-[ending-style]:opacity-0 transition-opacity duration-150",
className,
)}
{...props}
>
{children}
</BaseSelect.Popup>
</BaseSelect.Positioner>
</BaseSelect.Portal>
);
}
export function SelectItem({
className,
children,
...props
}: ComponentPropsWithoutRef<typeof BaseSelect.Item>) {
return (
<BaseSelect.Item
className={cn(
"relative flex cursor-default select-none items-center gap-2 rounded-sm py-1.5 pl-8 pr-2 text-sm text-fg outline-none",
"data-[highlighted]:bg-bg-muted",
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className,
)}
{...props}
>
<BaseSelect.ItemIndicator className="absolute left-2 inline-flex items-center text-accent">
<Check className="h-3.5 w-3.5" />
</BaseSelect.ItemIndicator>
<BaseSelect.ItemText>{children}</BaseSelect.ItemText>
</BaseSelect.Item>
);
}JavaFX
Ships in the PRIZM JavaFX library for thick-client C3 apps as PrizmSelect<T> (extends ComboBox<T>). Run the gallery to see it natively.
import design.prizm.fx.controls.PrizmSelect<T>;
PrizmSelect()
PrizmSelect(ObservableList<T> items)| Prop | Type | Default | Description |
|---|---|---|---|
| items | ObservableList<T> | — | The options — add via getItems().addAll(...). |
| value | ObjectProperty<T> | — | The selected item. |
Thin subclass of ComboBox; trigger + popup styled by the .combo-box / .combo-box-popup rules in prizm.css. Mirrors components/ui/select.tsx.