Select
A dropdown select component with groups, labels, and full keyboard navigation built on Radix UI.
Overview
The Select component is a composable dropdown built on Radix UI's Select primitive with design system tokens for consistent styling. It supports 3 validation variants, 3 sizes, grouped options, labels, separators, and full keyboard navigation.
Installation
Install the component via the CLI in one command.
npx @work-rjkashyap/unified-ui add selectpnpm dlx @work-rjkashyap/unified-ui add selectnpx @work-rjkashyap/unified-ui add selectbunx @work-rjkashyap/unified-ui add selectIf you haven't initialized your project yet, run npx @work-rjkashyap/unified-ui init first. See the CLI docs for details.
Or install the full package
Use this approach if you prefer to install the entire design system as a dependency instead of copying individual components.
npm install @work-rjkashyap/unified-uipnpm add @work-rjkashyap/unified-uiyarn add @work-rjkashyap/unified-uibun add @work-rjkashyap/unified-uiAnatomy
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectSeparator,
SelectTrigger,
SelectValue,
} from "@work-rjkashyap/unified-ui";Examples
Basic Usage
Variants
Sizes
| Size | Height | Font Size |
|---|---|---|
sm | 32px | 12px |
md | 36px | 14px |
lg | 40px | 14px |
With Groups
Disabled
With Error Message
Controlled
Use value and onValueChange for controlled usage.
const [value, setValue] = useState("");
<Select value={value} onValueChange={setValue}>
<SelectTrigger>
<SelectValue placeholder="Choose..." />
</SelectTrigger>
<SelectContent>
<SelectItem value="react">React</SelectItem>
<SelectItem value="vue">Vue</SelectItem>
<SelectItem value="svelte">Svelte</SelectItem>
</SelectContent>
</Select>;Anatomy
The Select is fully composable — each sub-component can be styled and positioned independently.
<Select>
<SelectTrigger variant="default" size="md">
<SelectValue placeholder="Pick one…" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Group label</SelectLabel>
<SelectItem value="a">Option A</SelectItem>
<SelectItem value="b">Option B</SelectItem>
</SelectGroup>
<SelectSeparator />
<SelectItem value="c">Option C</SelectItem>
</SelectContent>
</Select>Props
Select
Wraps Radix.Select.Root. All root props are forwarded.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Controlled selected value. |
defaultValue | string | — | Default value for uncontrolled usage. |
onValueChange | (value: string) => void | — | Callback when value changes. |
disabled | boolean | false | Disables the entire select. |
open | boolean | — | Controlled open state. |
onOpenChange | (open: boolean) => void | — | Callback when open state changes. |
name | string | — | Name for the hidden input (form submission). |
required | boolean | false | Marks the select as required. |
SelectTrigger
The button that opens the dropdown. Variant and size are set here.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "error" | "success" | "default" | Visual variant for validation state. |
size | "sm" | "md" | "lg" | "md" | Size of the trigger. Matches Button/Input heights. |
className | string | — | Additional CSS classes. |
SelectValue
Renders the selected value or placeholder text inside the trigger.
| Prop | Type | Default | Description |
|---|---|---|---|
placeholder | string | — | Placeholder text when no value is selected. |
SelectContent
The dropdown panel. Wraps items in a Portal for correct stacking.
| Prop | Type | Default | Description |
|---|---|---|---|
position | "popper" | "item-aligned" | "popper" | Positioning strategy for the dropdown. |
className | string | — | Additional CSS classes. |
SelectItem
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | required | The value for this option. |
disabled | boolean | false | Disables this specific item. |
className | string | — | Additional CSS classes. |
SelectGroup
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Additional CSS classes. |
SelectLabel
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Additional CSS classes. |
SelectSeparator
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Additional CSS classes. |
Accessibility
- Built on Radix UI Select for full ARIA compliance.
- Keyboard navigation — Arrow keys to navigate, Enter/Space to select, Escape to close.
- Type-ahead — Typing characters focuses matching items.
- Placeholder text uses
data-[placeholder]styling for muted appearance. - Focus ring is visible on keyboard navigation only (
focus-visible). - Disabled state uses both
disabledattribute andaria-disabled. - Error variant should be paired with descriptive text linked via
aria-describedby. - Groups with
SelectLabelprovide semantic grouping for screen readers.