Native Select
StableThe browser's own select element, styled to match prfct — best on mobile, in long forms and wherever zero JavaScript matters.
Installation
$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/native-select.jsonUsage
import {
NativeSelect,
NativeSelectOptGroup,
NativeSelectOption,
} from "@/components/ui/native-select"<NativeSelect defaultValue="yearly">
<NativeSelectOption value="monthly">Monthly</NativeSelectOption>
<NativeSelectOption value="yearly">Yearly</NativeSelectOption>
</NativeSelect>className styles the wrapper, which is w-fit by default — pass a width such as w-full to size the control. Every other prop goes to the <select> element.
Examples
Sizes
sm, default and lg match the heights of Input and Button, so a filter and its action line up.
Option groups
NativeSelectOptGroup adds non-selectable headings to long lists. Operating systems render them natively — indented on desktop, sectioned in mobile pickers.
Used for scheduled reports and reminders.
Invalid and disabled
A disabled, empty first option works as a placeholder: combined with required, the browser refuses to submit until a real choice is made. Mark invalid selections with aria-invalid and a FieldError, exactly as you would an input.
Guidelines
When to use
- Mobile-heavy flows: phones open their platform picker, which is faster and familiar.
- Long forms and server-rendered pages that must work before — or without — JavaScript.
- Simple lists of plain-text options where custom rendering adds nothing.
When not to use
- Options that need icons, descriptions or custom layout — use Select.
- Lists long enough to search — use a Combobox.
- Two to five options people should compare at a glance — use a Radio Group or Toggle Group.
Native or custom?
Choose one per product surface and stay consistent; mixing both in one form makes it feel unfinished.
Accessibility
Native Select is a real <select>, so it inherits the platform's keyboard support, screen reader semantics and form behavior with no scripting.
- Label it with a
FieldLabelandhtmlFor/id, or anaria-labelfor compact filters. - System colors. Options use the
CanvasandCanvasTextsystem colors, so the open list follows the operating system and the page'scolor-schemein dark mode. - Contrast. The border uses the
inputtoken at 3:1 against the page; the chevron is decorative and hidden from assistive technology.
| Key | Behavior |
|---|---|
Tab | Moves focus to the select. |
SpaceEnterAlt↓ | Opens the list (platform-dependent). |
↑↓ | Changes the selection — without opening the list on most desktop browsers. |
A–Z | Jumps to the next option starting with that letter. |
API reference
NativeSelect
Renders a wrapper <div> with a <select> and a chevron icon. Accepts all native select props.
NativeSelectOption
Renders an <option>. Accepts all native option props, including value and disabled.
NativeSelectOptGroup
Renders an <optgroup>. Set its label to the group heading.