Select
A native dropdown for choosing one option from a list. Extends the platform's built-in select with consistent sizing, labels, and error states.
Preview
Sizes
| Size | Height | Font size | Padding |
|---|---|---|---|
| sm | 32px | 12px | 8px 10px |
| md | 40px | 13px | 10px 12px |
| lg | 48px | 15px | 12px 16px |
States
This field is required
Implementation
Select.tsx
tsx
import { Select } from "@/components/ui/Select";
import { useState } from "react";
// Basic with placeholder
<Select label="Framework" placeholder="Choose a framework">
<option value="next">Next.js</option>
<option value="remix">Remix</option>
<option value="astro">Astro</option>
</Select>
// Controlled
const [region, setRegion] = useState("us-west");
<Select
label="Region"
value={region}
onChange={(e) => setRegion(e.target.value)}
>
<option value="us-east">US East</option>
<option value="us-west">US West</option>
<option value="eu">Europe</option>
</Select>
// Error state
<Select label="Status" error="Please select a status">
<option value="">Select status</option>
<option value="active">Active</option>
<option value="inactive">Inactive</option>
</Select>Props
All native <select> attributes are forwarded. Custom props are listed below.
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | Visible label rendered above the select. |
placeholder | string | — | Placeholder option shown when no value is selected. |
helperText | string | — | Supplemental hint rendered below the select. |
error | string | — | Error message. Replaces helperText and applies error styling. |
size | "sm" | "md" | "lg" | "md" | Controls height, padding, and font size. |
ARIA roles
| Element | Role | Key attributes |
|---|---|---|
| Trigger | combobox | aria-expanded, aria-haspopup='listbox', aria-labelledby |
| Dropdown | listbox | aria-label |
| Option | option | aria-selected |
Keyboard
| Key | Action |
|---|---|
| Space / Enter | Open the dropdown |
| Arrow Down / Up | Navigate between options (also opens if closed) |
| Enter | Select the focused option and close |
| Escape | Close the dropdown without selecting |
| Home / End | Jump to the first / last option |
| Tab | Close and move focus to the next element |
Accessibility
- →Uses a native <select> element — fully keyboard navigable and compatible with all assistive technology.
- →The label prop renders a <label> element properly associated via htmlFor.
- →Error messages are surfaced as visible text; pair with aria-describedby for screen readers.
- →Disabled state is communicated natively via the disabled attribute.
- →ChevronDown overlay uses pointer-events:none so it does not interfere with the native control.