Select
A custom select primitive with trigger, value, grouped options, selected indicators, scroll affordances, and native hidden form values.
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from 'radcn/select'Live package example
Render the upstream fruit Select and grouped timezone Select examples with RadCN package primitives and app-owned option data.
Demo and Scrollable
Render the upstream fruit Select and grouped timezone Select examples with RadCN package primitives and app-owned option data.
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectScrollDownButton,
SelectScrollUpButton,
SelectTrigger,
SelectValue,
SelectViewport,
} from 'radcn/select'
const fruits = [
['apple', 'Apple'],
['banana', 'Banana'],
['blueberry', 'Blueberry'],
['grapes', 'Grapes'],
['pineapple', 'Pineapple'],
]
const timezones = [
['North America', [
['est', 'Eastern Standard Time (EST)'],
['cst', 'Central Standard Time (CST)'],
['mst', 'Mountain Standard Time (MST)'],
['pst', 'Pacific Standard Time (PST)'],
['akst', 'Alaska Standard Time (AKST)'],
['hst', 'Hawaii Standard Time (HST)'],
]],
['Europe & Africa', [
['gmt', 'Greenwich Mean Time (GMT)'],
['cet', 'Central European Time (CET)'],
['eet', 'Eastern European Time (EET)'],
['west', 'Western European Summer Time (WEST)'],
['cat', 'Central Africa Time (CAT)'],
['eat', 'East Africa Time (EAT)'],
]],
['Asia', [
['msk', 'Moscow Time (MSK)'],
['ist', 'India Standard Time (IST)'],
['cst_china', 'China Standard Time (CST)'],
['jst', 'Japan Standard Time (JST)'],
['kst', 'Korea Standard Time (KST)'],
['ist_indonesia', 'Indonesia Central Standard Time (WITA)'],
]],
['Australia & Pacific', [
['awst', 'Australian Western Standard Time (AWST)'],
['acst', 'Australian Central Standard Time (ACST)'],
['aest', 'Australian Eastern Standard Time (AEST)'],
['nzst', 'New Zealand Standard Time (NZST)'],
['fjt', 'Fiji Time (FJT)'],
]],
['South America', [
['art', 'Argentina Time (ART)'],
['bot', 'Bolivia Time (BOT)'],
['brt', 'Brasilia Time (BRT)'],
['clt', 'Chile Standard Time (CLT)'],
]],
]
export function SelectPreview() {
return (
<>
<Select name="fruit" style="width:180px;">
<SelectTrigger ariaLabel="Fruit">
<SelectValue placeholder="Select a fruit" />
</SelectTrigger>
<SelectContent>
<SelectViewport>
<SelectGroup>
<SelectLabel>Fruits</SelectLabel>
{fruits.map(([value, label]) => (
<SelectItem textValue={label} value={value}>{label}</SelectItem>
))}
</SelectGroup>
</SelectViewport>
</SelectContent>
</Select>
<Select name="timezone" style="width:280px;">
<SelectTrigger ariaLabel="Timezone">
<SelectValue placeholder="Select a timezone" />
</SelectTrigger>
<SelectContent>
<SelectScrollUpButton />
<SelectViewport style="max-height:12rem;overflow:auto;">
{timezones.map(([group, options]) => (
<SelectGroup>
<SelectLabel>{group}</SelectLabel>
{options.map(([value, label]) => (
<SelectItem textValue={label} value={value}>{label}</SelectItem>
))}
</SelectGroup>
))}
</SelectViewport>
<SelectScrollDownButton />
</SelectContent>
</Select>
</>
)
}Installation
Intended future install command. RadCN is private and not published to npm yet, so this snippet documents the target user-facing API rather than something external consumers can run today.
pnpm add radcn # intended future package
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from 'radcn/select'Theming
RadCN tokens read the resolved theme from the document. Store the user's preference separately, then resolve system preferences to a concrete light or dark theme before setting package tokens.
<html data-radcn-theme-mode="system" data-radcn-theme="dark">
...
</html>Accessibility
- SelectTrigger renders a button with combobox semantics after enhancement while SelectViewport owns listbox semantics.
- SelectItem renders role="option" with aria-selected and selected indicator hooks.
- SelectGroup and SelectLabel provide visible grouping for fruit and timezone option sets.
- When name is provided, Select synchronizes the selected value to a native hidden input for form submission and reset behavior.
Customization
- Select exposes root, trigger, value, content, viewport, group, label, item, indicator, separator, scroll button, and hidden input hooks through data-radcn-select* attributes.
- Trigger widths such as w-[180px] and w-[280px] map to class, style, CSS variables, or app CSS rather than Tailwind utilities.
- Fruit options, timezone groups, option labels, submitted values, and selected display text remain app-owned data rendered through RadCN item primitives.
- Scroll buttons, viewport height, popper placement, custom classes, styles, and tokens are explicit RadCN props or app CSS extension points.
Remix 3 Notes
- React props, Radix SelectPrimitive, className, data-slot, Tailwind utilities, cn, and vendor source map to explicit RadCN props, class, public data hooks, package CSS, inline style, and CSS variables.
- CheckIcon, ChevronDownIcon, ChevronUpIcon, and lucide-react are presentation choices; RadCN provides dependency-free indicators and trigger glyphs.
- Portal behavior is supported through SelectPortal when an app needs it, but the named docs examples keep content scoped for visible documentation evidence.
- React state and onValueChange map to package-owned browser enhancement, native hidden values, route state, or app-owned event handling.
- vendor source remains read-only evidence and is not imported by RadCN.
