Unified UI

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 select
pnpm dlx @work-rjkashyap/unified-ui add select
npx @work-rjkashyap/unified-ui add select
bunx @work-rjkashyap/unified-ui add select

If 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-ui
pnpm add @work-rjkashyap/unified-ui
yarn add @work-rjkashyap/unified-ui
bun add @work-rjkashyap/unified-ui

Anatomy

import {
	Select,
	SelectContent,
	SelectGroup,
	SelectItem,
	SelectLabel,
	SelectSeparator,
	SelectTrigger,
	SelectValue,
} from "@work-rjkashyap/unified-ui";

Examples

Basic Usage

Variants

Sizes

SizeHeightFont Size
sm32px12px
md36px14px
lg40px14px

With Groups

Disabled

With Error Message

Please select a role to continue.

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.

PropTypeDefaultDescription
valuestringControlled selected value.
defaultValuestringDefault value for uncontrolled usage.
onValueChange(value: string) => voidCallback when value changes.
disabledbooleanfalseDisables the entire select.
openbooleanControlled open state.
onOpenChange(open: boolean) => voidCallback when open state changes.
namestringName for the hidden input (form submission).
requiredbooleanfalseMarks the select as required.

SelectTrigger

The button that opens the dropdown. Variant and size are set here.

PropTypeDefaultDescription
variant"default" | "error" | "success""default"Visual variant for validation state.
size"sm" | "md" | "lg""md"Size of the trigger. Matches Button/Input heights.
classNamestringAdditional CSS classes.

SelectValue

Renders the selected value or placeholder text inside the trigger.

PropTypeDefaultDescription
placeholderstringPlaceholder text when no value is selected.

SelectContent

The dropdown panel. Wraps items in a Portal for correct stacking.

PropTypeDefaultDescription
position"popper" | "item-aligned""popper"Positioning strategy for the dropdown.
classNamestringAdditional CSS classes.

SelectItem

PropTypeDefaultDescription
valuestringrequiredThe value for this option.
disabledbooleanfalseDisables this specific item.
classNamestringAdditional CSS classes.

SelectGroup

PropTypeDefaultDescription
classNamestringAdditional CSS classes.

SelectLabel

PropTypeDefaultDescription
classNamestringAdditional CSS classes.

SelectSeparator

PropTypeDefaultDescription
classNamestringAdditional 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 disabled attribute and aria-disabled.
  • Error variant should be paired with descriptive text linked via aria-describedby.
  • Groups with SelectLabel provide semantic grouping for screen readers.

On this page