Components / Select

SelectPrimitive

Native select wrapped with a custom chevron and matching Input styling. The browser handles keyboard and screen-reader behaviour better than a custom dropdown.

Section: Components

Examples

Default

usage.astro | astro
<SelectPrimitive
  label="Country"
  name="country"
  options={[
    { value: 'no', label: 'Norway' },
    { value: 'se', label: 'Sweden' },
    { value: 'dk', label: 'Denmark' },
    { value: 'fi', label: 'Finland' },
    { value: 'is', label: 'Iceland' },
  ]}
  placeholder="Choose a country…"
/>

With hint + preselected value

Used to determine your tax region.

usage.astro | astro
<SelectPrimitive
  label="Country"
  name="country"
  options={countryOptions}
  value="no"
  hint="Used to determine your tax region."
/>

With a disabled option

'Urgent' is reserved for paid plans.

usage.astro | astro
<SelectPrimitive
  label="Priority"
  name="priority"
  options={[
    { value: 'low',    label: 'Low' },
    { value: 'med',    label: 'Medium' },
    { value: 'high',   label: 'High' },
    { value: 'urgent', label: 'Urgent', disabled: true },
  ]}
  placeholder="Select priority…"
  hint="'Urgent' is reserved for paid plans."
/>

Error state

usage.astro | astro
<SelectPrimitive
  label="Country"
  name="country"
  options={countryOptions}
  placeholder="Choose a country…"
  error="Please pick a country before continuing."
  required
/>

Success state

Region verified against your billing address.

usage.astro | astro
<SelectPrimitive
  label="Verified region"
  name="verified-region"
  options={countryOptions}
  value="se"
  variant="success"
  hint="Region verified against your billing address."
/>

Sizes

usage.astro | astro
<SelectPrimitive label="Small"  name="size-sm" size="sm" options={countryOptions} placeholder="sm" />
<SelectPrimitive label="Medium" name="size-md" size="md" options={countryOptions} placeholder="md" />
<SelectPrimitive label="Large"  name="size-lg" size="lg" options={countryOptions} placeholder="lg" />

Disabled

usage.astro | astro
<SelectPrimitive
  label="Locked region"
  name="locked-region"
  options={countryOptions}
  value="no"
  disabled
/>

Anatomy

Property Behavior
Label Renders above the trigger as a real `<label for>`.
Trigger Native `<select>` styled to match Input. Chevron is a CSS background-image.
Chevron Static down-chevron icon at the suffix position — cosmetic only.
Hint Plain helper text below the trigger; `aria-describedby` is wired automatically.
Error Replaces the hint when `error` is set; toggles `aria-invalid="true"`.

Accessibility

  • Renders a real native <select>, so keyboard navigation (typeahead, ArrowUp/Down, Home/End) and the platform's own option dialog are inherited from the browser.
  • label renders as a paired <label for>; clicking the label focuses the select.
  • hint + error are wired via aria-describedby and announced by SR after the field's name.
  • Setting error sets aria-invalid="true" on the trigger.
  • Disabled options use the native disabled attribute, so SR announce them as "dimmed" / "unavailable."
  • Focus uses the system focus ring (--ds-shadow-focus-ring) — visible on every surface.

Do / Don't

Property Do Don't
Native first Use SelectPrimitive for short, flat option lists where the browser picker is acceptable. Reach for SelectPrimitive when you need grouping, search, or rich option rendering — wait for the Combobox primitive.
Option count Keep total options under ~12; sort alphabetically or by frequency. Dump 200 items into the native picker — UX collapses on mobile.
Placeholder Show a `placeholder` only when no `value` makes sense as default. Use the placeholder to convey constraints — put those in `hint`.
Disabled opts Mark a single option `disabled: true` when context (plan, role) forbids it. Disable the whole select to hide that an option exists — surface why instead.
Error copy Explain what changed ("Pick a country before continuing"). Use vague copy ("Invalid") — users have no way to recover.

Props

Property Type Default
label string required
name string required
options {value, label, disabled?}[] required
value string -
placeholder string -
hint string -
error string -
variant default | error | success 'default'
size sm | md | lg 'md'
required boolean false
disabled boolean false
className string ''
SelectPrimitive props

Source

SelectPrimitive.astro | astro
<SelectPrimitive
  label="Country"
  name="country"
  options={[
    { value: 'no', label: 'Norway' },
    { value: 'se', label: 'Sweden' },
    { value: 'dk', label: 'Denmark' },
  ]}
  placeholder="Choose a country…"
  hint="Used to determine your tax region."
/>

<SelectPrimitive
  label="Priority"
  name="priority"
  options={[
    { value: 'low',    label: 'Low' },
    { value: 'med',    label: 'Medium' },
    { value: 'high',   label: 'High' },
    { value: 'urgent', label: 'Urgent', disabled: true },
  ]}
  error="Please pick a priority."
  required
/>