Select
Choose one value from a short predefined list. Radix Select styled with Yuno tokens. Trigger matches Input (h-9, rounded-md, flat border).
Anatomy
- 1Label
Describes what is being selected. Sits above the trigger, same as any form field.
- 2Trigger
The clickable pill. Shows the current value or placeholder + a trailing CaretDown.
- 3Content
The popover with the option list. Elevated with shadow-lg on rounded-md. Portalled to the body.
- 4Item
A single option. Focus state uses bg-accent. Selected shows a Check indicator on the right.
Form field
<div className="grid w-full max-w-sm gap-1.5">
<Label htmlFor="currency">Currency</Label>
<Select>
<SelectTrigger id="currency">
<SelectValue placeholder="Choose currency" />
</SelectTrigger>
<SelectContent>
<SelectItem value="usd">USD - US Dollar</SelectItem>
<SelectItem value="cop">COP - Colombian Peso</SelectItem>
<SelectItem value="mxn">MXN - Mexican Peso</SelectItem>
<SelectItem value="brl">BRL - Brazilian Real</SelectItem>
</SelectContent>
</Select>
</div>With icons
<Select>
<SelectTrigger className="w-64">
<div className="flex items-center gap-2">
<Globe weight="light" className="size-4 text-muted-foreground" />
<SelectValue placeholder="Choose language" />
</div>
</SelectTrigger>
<SelectContent>
<SelectItem value="en">English</SelectItem>
<SelectItem value="es">Español</SelectItem>
<SelectItem value="pt">Português</SelectItem>
</SelectContent>
</Select>Groups
Long option lists group with SelectGroup + SelectLabel headers (all caps, muted). SelectSeparator draws a hairline between groups.
<Select>
<SelectTrigger className="w-72">
<SelectValue placeholder="Choose destination" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Latam</SelectLabel>
<SelectItem value="co">Colombia</SelectItem>
<SelectItem value="mx">Mexico</SelectItem>
<SelectItem value="br">Brazil</SelectItem>
<SelectItem value="ar">Argentina</SelectItem>
</SelectGroup>
<SelectSeparator />
<SelectGroup>
<SelectLabel>North America</SelectLabel>
<SelectItem value="us">United States</SelectItem>
<SelectItem value="ca">Canada</SelectItem>
</SelectGroup>
<SelectSeparator />
<SelectGroup>
<SelectLabel>Europe</SelectLabel>
<SelectItem value="es">Spain</SelectItem>
<SelectItem value="pt">Portugal</SelectItem>
<SelectItem value="uk">United Kingdom</SelectItem>
</SelectGroup>
</SelectContent>
</Select>Disabled options
<Select>
<SelectTrigger className="w-64">
<SelectValue placeholder="Choose plan" />
</SelectTrigger>
<SelectContent>
<SelectItem value="starter">Starter</SelectItem>
<SelectItem value="growth">Growth</SelectItem>
<SelectItem value="scale" disabled>Scale (contact sales)</SelectItem>
</SelectContent>
</Select>States
<Select>
<SelectTrigger className="w-56"><SelectValue placeholder="Choose currency" /></SelectTrigger>
<SelectContent>
<SelectItem value="usd">USD</SelectItem>
<SelectItem value="cop">COP</SelectItem>
</SelectContent>
</Select><Select disabled>
<SelectTrigger className="w-56"><SelectValue placeholder="Managed by admin" /></SelectTrigger>
</Select>Please choose a plan to continue.
<Select>
<SelectTrigger
aria-invalid
className="w-56 border-destructive focus:border-destructive focus:ring-destructive/30"
>
<SelectValue placeholder="Choose plan" />
</SelectTrigger>
</Select>
<p className="text-xs text-destructive">Please choose a plan to continue.</p>Required and optional
Yuno marks the odd one out. If most fields in a form are required, mark the few Optional ones with a small muted 'Optional' to the right of the Label. If most are optional, mark the required ones with a discrete 'Required' in the same spot. Never mix asterisks and Optional labels in the same form.
<div className="grid gap-1.5 w-full max-w-sm">
<div className="flex items-center justify-between">
<Label htmlFor="tz">Timezone</Label>
<span className="text-xs text-muted-foreground">Optional</span>
</div>
<Select>
<SelectTrigger id="tz"><SelectValue placeholder="Choose timezone" /></SelectTrigger>
<SelectContent><SelectItem value="utc">UTC</SelectItem></SelectContent>
</Select>
</div><div className="grid gap-1.5 w-full max-w-sm">
<div className="flex items-center justify-between">
<Label htmlFor="currency">Currency</Label>
<span className="text-xs text-muted-foreground">Required</span>
</div>
<Select required>
<SelectTrigger id="currency"><SelectValue placeholder="Choose currency" /></SelectTrigger>
<SelectContent><SelectItem value="usd">USD</SelectItem></SelectContent>
</Select>
</div>Recipes
Ready-to-copy compositions covering the most common Yuno usages of this atom.
Short list of currencies inside a form. Trigger width matches sibling inputs.
<div className="grid gap-1.5 w-full max-w-sm">
<Label htmlFor="currency">Currency</Label>
<Select>
<SelectTrigger id="currency"><SelectValue placeholder="Choose currency" /></SelectTrigger>
<SelectContent>
<SelectItem value="usd">USD</SelectItem>
<SelectItem value="cop">COP</SelectItem>
<SelectItem value="mxn">MXN</SelectItem>
</SelectContent>
</Select>
</div>Countries grouped by region using SelectLabel + SelectSeparator to make long lists scannable.
<Select>
<SelectTrigger className="w-72"><SelectValue placeholder="Choose country" /></SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Latam</SelectLabel>
<SelectItem value="co">Colombia</SelectItem>
<SelectItem value="mx">Mexico</SelectItem>
</SelectGroup>
<SelectSeparator />
<SelectGroup>
<SelectLabel>Europe</SelectLabel>
<SelectItem value="es">Spain</SelectItem>
</SelectGroup>
</SelectContent>
</Select>Compact select above a table or list. Leading Sort icon inside the trigger clarifies intent.
<Select defaultValue="newest">
<SelectTrigger className="w-56">
<div className="flex items-center gap-2">
<ArrowsDownUp weight="light" className="size-4 text-muted-foreground" />
<SelectValue />
</div>
</SelectTrigger>
<SelectContent>
<SelectItem value="newest">Newest first</SelectItem>
<SelectItem value="oldest">Oldest first</SelectItem>
<SelectItem value="amount">Highest amount</SelectItem>
</SelectContent>
</Select>Plans list where a tier is disabled with a hint text so the user knows it's not available.
<Select>
<SelectTrigger className="w-64"><SelectValue placeholder="Choose plan" /></SelectTrigger>
<SelectContent>
<SelectItem value="starter">Starter</SelectItem>
<SelectItem value="growth">Growth</SelectItem>
<SelectItem value="scale" disabled>Scale (contact sales)</SelectItem>
</SelectContent>
</Select>Import
Copy this import line at the top of the file where you compose this atom.
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectSeparator,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Label } from "@/components/ui/label";Props
Everything else from the underlying HTML or Radix primitive is forwarded via ...props.
| Prop | Type | Default | Description |
|---|---|---|---|
| value / defaultValue | string | — | Selected item value. Radix keeps value as a string. |
| onValueChange | (value: string) => void | — | Fires when the user picks a new option. |
| disabled | boolean | false | Applied on <Select> or per <SelectItem> to disable individual options. |
| required | boolean | false | Native form validation. Pair with the 'Required' label pattern in this doc. |
| children | SelectTrigger + SelectContent (with SelectGroup / SelectLabel / SelectItem / SelectSeparator) | — | Compound API. See Groups section for the canonical structure. |
| SelectTrigger.className | string | — | Merged via cn(). Use w-* utilities to set trigger width. Do not add shadow-*. |
When to use
- Choose one from 3–12 options (currency, country, status).
- The list is stable and doesn't need search.
- Inside a form, paired with a Label above the trigger.
When not to use
- Fewer than 3 options — use RadioGroup or a segmented control.
- More than ~12 or needs search — use Combobox / Command.
- Multi-select — use a Checkbox group or a MultiSelect.
- For actions (edit, delete, share) — that's a DropdownMenu.
Usage
- Provide a clear placeholder ('Choose currency').
- Order options meaningfully (frequency, alphabetical, logical).
- Keep the trigger width consistent with sibling inputs in the same form.
- Use SelectGroup + SelectLabel to structure long lists into scannable sections.
- Don't nest a Select inside another Select — it collapses on mobile.
- Don't use a Select for actions — that's a DropdownMenu.
- Don't apply drop shadow on the trigger — only border.
- Don't rely on the trigger to fit long option labels — it will truncate.
Related
Cross-links to atoms and patterns you may reach for next.
- Radio groupFor 2–5 options where all should be visible.
- CommandFor long lists that need search.
- Dropdown menuFor actions (edit / delete / share), not for choosing a value.
- ComboboxCompose Command inside a Popover for a filterable select.