# Select

## Overview

The select component supports native single-select fields for choosing one value from a predefined list.

The component pattern uses a native `<label>` that wraps a native `<select>`, so the control can be styled without requiring a classed wrapper.

## When to use

Use select when users choose one value from a known set and native browser selection and validation semantics should remain intact.

## When not to use

Do not use select for a small set that should remain visible, multiple independent choices, or free-form entry; use radios, checkboxes, or input.

## Usage

```html
<label>
  <span>Which BYU Creamery ice cream should we scoop?</span>
  <select required>
    <option value="" selected disabled>Select a flavor</option>
    <option>Graham Canyon</option>
    <option>Mint Brownie</option>
    <option>Peaches and Cream</option>
  </select>
</label>

```

Use this component when the user needs to choose one option from a known set and native browser form semantics should remain intact.

Use radios instead when a single small set should stay visible at once, checkboxes when users may choose more than one option, or a text input when users need to enter a freeform value.

The label should remain visible above the field rather than relying on the initial option as the only field description.

The field should use native `<label>` and `<select>` elements so the control keeps browser form behavior, keyboard support, and assistive technology semantics.

## Behavior

Covered by [Playwright behavior tests](../../tests/e2e/forms-inputs.spec.js).

- SEL-001: Single-select fields render a control-owned downward chevron treatment while preserving native select semantics.
- SEL-002: Single-select fields reserve inline space for the chevron indicator so text and the icon do not collide.
- SEL-003: The chevron source is controlled by `--select-icon-source`, which should resolve to a complete background image so consumers can replace the default indicator without rewriting component selectors.
- SEL-004: The chevron offset, size, and reserved space should derive from shared layout theme tokens rather than hardcoded component-only measurements.
- SEL-005: Single-select fields can start with muted text color and switch to the default text color once the field becomes `:valid`.
- SEL-006: Multi-select fields and sized listboxes keep the browser-native listbox appearance instead of forcing a dropdown chevron treatment.
- SEL-007: Multi-select fields remain styled for exceptional or legacy cases, but checkboxes should be the default pattern for nearly all multi-choice fields.
- SEL-008: Focus must remain clearly visible for keyboard users.
- SEL-009: Comfortable and compact density should come from the layout theme tokens rather than select-specific spacing values.
- SEL-010: Single-select controls match button and single-line input heights across comfortable and compact layout themes.
## Accessibility

- Use a native `<label>` so the field stays explicitly named.
- If the label does not wrap the select, associate them with matching `for` and `id` attributes.
- Do not rely on the initial placeholder-like option as the only label for the field.
- Keep option text descriptive enough to make sense when announced on its own.
- Use native constraints such as `required` when the first option is only a prompt and not a valid selection.
- Prefer checkbox groups when users can choose multiple values.
- If an exceptional or legacy `multiple` select is necessary, use the `size` attribute so enough options remain visible without extra scrolling.
- If a select is meant to render as a listbox, keep the native `size` or `multiple` behavior rather than trying to force the single-select chevron treatment onto it.
- Intentionally do not try to style the native select menu or picker. Custom picker treatments can break assistive technology behavior, add maintenance cost, and become brittle across browsers and operating systems.
- Revisit this once the newer browser-native customizable select features are supported in Firefox and Safari. [Browser compatibility](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select#browser_compatibility) already shows support across most major browsers, and it gives us a cleaner future opt-in path than replacing the native picker ourselves.

## Variables

| Variable | Type | Description |
| --- | --- | --- |
| `--select-color-border-subtle` | `<color>` | Sets --select-color-border-subtle so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--select-color-focus-ring` | `<color>` | Sets --select-color-focus-ring so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--select-color-primary` | `<color>` | Sets --select-color-primary so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--select-color-text` | `<color>` | Sets --select-color-text so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--select-color-text-accent` | `<color>` | Sets --select-color-text-accent so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--select-color-text-subtle` | `<color>` | Sets --select-color-text-subtle so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--select-control-border-width` | `<length>` | Sets --select-control-border-width so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--select-control-gap` | `<length>` | Sets --select-control-gap so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--select-control-min-height` | `<length>` | Sets --select-control-min-height so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--select-control-padding-block` | `<length>` | Sets --select-control-padding-block so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--select-control-padding-inline` | `<length>` | Sets --select-control-padding-inline so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--select-control-radius` | `<length>` | Sets --select-control-radius so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--select-focus-ring-size` | `<length>` | Sets --select-focus-ring-size so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--select-font-size` | `<length>` | Sets --select-font-size so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--select-icon-offset` | `<length>` | Sets the inline offset between the select chevron and the control edge; change it when padding or icon alignment changes. |
| `--select-icon-size` | `<length>` | Sets the select chevron size; change it when the indicator should scale differently from the field text. |
| `--select-icon-source` | `<image> | none` | Sets the chevron image used by select fields; change it to swap the indicator artwork or color. |
| `--select-line-height` | `<number>` | Sets --select-line-height so the component can default to shared theme or layout tokens while exposing an overrideable component API. |

## Depends On

- `--color-border-subtle`
- `--color-focus-ring`
- `--color-primary`
- `--color-text`
- `--color-text-accent`
- `--color-text-subtle`
- `--font-line-height-body`
- `--font-size`
- `--layout-control-border-width`
- `--layout-control-gap`
- `--layout-control-icon-size`
- `--layout-control-min-height`
- `--layout-control-padding-block`
- `--layout-control-padding-inline`
- `--layout-control-radius`
- `--layout-focus-ring-size`
- `--layout-space-inline`
