Native select
Picks one option with the browser's own select.
Installation
The CLI installs the Radix or Base UI file to match your project.
If your project doesn't have Wisty UI's theme yet, add it once with npx shadcn@latest add @wisty/cosmos. Until then, components keep shadcn's default look. Installation has the details.
When to use
Use it
- People pick one option from a short, fixed list, and the browser's own list is fine.
- The form must work on touch devices with the system picker, or without JavaScript.
- The options come in groups, like inbound and outbound lead sources.
Don't use it
- The list should look like the rest of the app, or options need icons or descriptions. Use Select.
- The list is long or people should search it. Use Combobox.
- People may pick several options. Use checkboxes.
- There are two to five options and room to show them all. Use Radio group.
Usage
NativeSelect
├── NativeSelectOption
└── NativeSelectOptGroup
└── NativeSelectOptionPass id to NativeSelect, so a label's htmlFor reaches the select. Start with an empty option when people must choose.
import { Field, FieldLabel } from "@/components/ui/field"
import { NativeSelect, NativeSelectOption } from "@/components/ui/native-select"<Field>
<FieldLabel htmlFor="rating">Rating</FieldLabel>
<NativeSelect id="rating" defaultValue="">
<NativeSelectOption value="">Select an option</NativeSelectOption>
<NativeSelectOption value="hot">Hot</NativeSelectOption>
<NativeSelectOption value="cold">Cold</NativeSelectOption>
</NativeSelect>
</Field>className goes to the wrapper around the select, so width classes size the whole field. Every other prop goes to the select.
Examples
States
One with `aria-invalid` and an error message it points to, and one `disabled`.
Sizes
The default and small selects, set with `size` on `NativeSelect`.
API reference
| Part | Built on |
|---|---|
NativeSelect | <select> (opens in a new tab) |
NativeSelectOption | <option> (opens in a new tab) |
NativeSelectOptGroup | <optgroup> (opens in a new tab) |
NativeSelect
| Prop | Type | Default |
|---|---|---|
size | "sm" | "default" | "default" |
SLDS mapping
NativeSelect is slds-select_container around slds-select, drawn with the input's frame. aria-invalid is slds-has-error, and disabled is SLDS's gray disabled field, not dimmed. Options and option groups keep the browser's colors.
Known gaps:
- SLDS draws two small triangles, up and down. This draws one chevron.
| Prop | Value | SLDS | Notes |
|---|---|---|---|
size | default | slds-select_container slds-select | 32px, like an input. |
size | sm | none | SLDS has one select height. 28px, like a small button. |
Accessibility
- Name it with a visible label. The empty first option isn't a label.
- Pair
aria-invalidwith an error message the select points to througharia-describedby. - In Cosmos dark, text in an invalid select is about 4.3:1 against its background, below AA. Salesforce's own stylesheet fails the same way.
Responsive behavior
- In a vertical Field it fills the column. Elsewhere it's as wide as its longest option; add
w-fullto fill its container. - When the field is narrower than an option, the option's text is cut off before the chevron.
- On touch screens the text is larger, so iOS Safari doesn't zoom in on focus. Don't set a smaller text size on it.
Rules
- Use
NativeSelectOptionandNativeSelectOptGroup, not bareoptionandoptgroup, so the options keep readable colors in dark mode. - Show errors with
aria-invalid. Don't add border or color classes.