Inputs/Native Select

Native Select

A native HTML select element with custom styling.

Themed

When to Use

Use Native Select when you need to:

  • Provide a dropdown with native browser behavior and mobile-optimized pickers
  • Allow users to choose a single option from a predefined list of 5-15 items
  • Use a form control that works without JavaScript for progressive enhancement
  • Leverage the operating system's native accessibility features for selection
  • Group related options into categories using option groups

When Not to Use

  • Custom styled dropdowns with animations - use Select
  • Searchable or filterable option lists - use Combobox
  • Fewer than 3 mutually exclusive options - use Radio Group
  • Multi-selection or complex option rendering with icons, avatars, or descriptions

Default

A native select with a list of status options.

With Groups

Organize options into logical categories using NativeSelectOptGroup for better scannability.

Disabled

Disabled state prevents all user interaction and reduces opacity to indicate unavailability.

Invalid State

Show validation errors with the aria-invalid attribute. Applies a destructive border and ring color.

Form Example

Native select paired with a Label component inside a form layout for proper accessibility.

UX & Design Guidelines

Visual Hierarchy

Native selects use a subtle border and chevron icon to signal interactivity. The chevron is styled with text-muted-foreground at 50% opacity to remain visible without competing with the selected value text. Use a placeholder option (empty value) as the first option to prompt selection.

Spacing & Layout

The default height is h-9 (36px) with px-3 py-2 padding. Use size="sm" for compact layouts at h-8 (32px). When placing selects in forms, maintain consistent spacing with gap-4 between form fields.

Responsive Behavior

Native selects automatically use the platform's native picker on mobile devices, providing a familiar scrolling interface on iOS and a dropdown dialog on Android. The wrapper uses w-fit by default; apply w-full to the wrapper for full-width selects in responsive form layouts.

Color & Contrast

The select uses border-input for the border and transparent background in light mode. In dark mode, it applies dark:bg-input/30 with a hover state of dark:hover:bg-input/50 for subtle visual feedback. Selection highlighting uses bg-primary with text-primary-foreground.

Accessibility

Keyboard Navigation

  • Tab — Move focus to/from the select
  • Space or Enter — Open the dropdown on most browsers
  • Arrow Up / Arrow Down — Navigate through options
  • Home / End — Jump to first/last option
  • Type a character to jump to matching options (native type-ahead)

Screen Reader Support

  • Native HTML <select> provides built-in screen reader support
  • Options and option groups are announced with their labels automatically
  • The currently selected value is read aloud when the select receives focus
  • Use a visible <Label> with matching htmlFor and id for best results

Focus Management

Focus ring uses focus-visible:ring-[3px] with ring-ring/50 color and focus-visible:border-ring. Invalid selects display a destructive ring with aria-invalid:ring-destructive/20. The decorative chevron icon is marked aria-hidden="true" so it does not interfere with assistive technology.

ARIA Attributes

{/* Associate with a visible label */}
<Label htmlFor="country">Country</Label>
<NativeSelect id="country">
  <NativeSelectOption value="">Select a country</NativeSelectOption>
  <NativeSelectOption value="us">United States</NativeSelectOption>
</NativeSelect>

{/* Standalone select with aria-label */}
<NativeSelect aria-label="Filter by status">
  <NativeSelectOption value="">All statuses</NativeSelectOption>
  <NativeSelectOption value="active">Active</NativeSelectOption>
  <NativeSelectOption value="archived">Archived</NativeSelectOption>
</NativeSelect>

{/* Invalid state with error description */}
<NativeSelect
  aria-invalid="true"
  aria-describedby="role-error"
>
  <NativeSelectOption value="">Select role</NativeSelectOption>
</NativeSelect>
<span id="role-error" className="text-sm text-destructive">
  Please select a role
</span>

API Reference

The NativeSelect component accepts the following props in addition to standard HTML select attributes.

PropTypeDefaultDescription
size"sm" | "default""default"The size of the select. Small size reduces height.
disabledbooleanfalseWhen true, prevents user interaction and applies disabled styles.
aria-invalidboolean | stringfalseWhen true, applies error/invalid styling with destructive border and ring.
aria-labelstringAccessible label for the select when no visible label is present.
classNamestringAdditional CSS classes to apply to the select element.

NativeSelectOption Props

Individual option within the select. Extends standard HTML option attributes.

PropTypeDefaultDescription
valuestringThe value submitted with the form when this option is selected.
disabledbooleanfalseWhen true, prevents selection of this option.
classNamestringAdditional CSS classes to apply to the option.

NativeSelectOptGroup Props

Groups related options together with a visible label. Extends standard HTML optgroup attributes.

PropTypeDefaultDescription
labelstringThe visible label for the option group.
disabledbooleanfalseWhen true, disables all options within the group.
classNamestringAdditional CSS classes to apply to the option group.