---
outline: deep
---

# Select

Selects are used to pick a single option from a dropdown list. Commonly used in forms for choosing categories, countries, or any predefined set of values.

Built on the [Customizable Select API](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select) (`appearance: base-select`). Where unsupported it degrades to a native `<select>` — so always keep meaningful text in each `<option>`.

**`.l-select`** — Native HTML Element

## Options

### Basic

Add `class="l-select"` to a native `<select>` and `class="l-select-item"` to each `<option>`.

```html
<select
  class="l-select"
  aria-label="Plan"
>
  <option
    class="l-select-item"
    value="free"
  >
    Free
  </option>
  <option
    class="l-select-item"
    value="pro"
  >
    Pro
  </option>
  <option
    class="l-select-item"
    value="team"
  >
    Team
  </option>
</select>
```

### Rich options

Put any HTML inside an `<option>`. Wrap a `.l-select-item-title` over a `.l-select-item-description` in `.l-select-item-text` (add a `.l-select-item-media` image or icon before it if needed). A `<button><selectedcontent></button>` trigger mirrors the chosen option — the description is hidden there to keep it compact.

```html
<select
  class="l-select"
  aria-label="Merge method"
>
  <button>
    <selectedcontent></selectedcontent>
  </button>

  <option
    class="l-select-item"
    value="squash"
    selected
  >
    <span class="l-select-item-text">
      <span class="l-select-item-title">Squash and merge</span>
      <span class="l-select-item-description">
        The 1 commit from this branch will be added to the base branch.
      </span>
    </span>
  </option>

  <option
    class="l-select-item"
    value="rebase"
  >
    <span class="l-select-item-text">
      <span class="l-select-item-title">Rebase and merge</span>
      <span class="l-select-item-description">
        The 1 commit from this branch will be rebased and added to the base branch.
      </span>
    </span>
  </option>
</select>
```

## Accessibility

### Criteria

- **Role** — Uses native `<select>` — built-in `combobox`/`listbox` semantics
- **Accessible name** — Must have an associated `<label>` element
- **Disabled state** — Native `disabled` attribute prevents interaction and announces as disabled
- **Required state** — Native `required` attribute communicates mandatory field to assistive tech

### Rules

- Always pair the `<select>` with a visible `<label>` element using `for`/`id`
- Use native `<option>` elements for choices — the browser handles all ARIA semantics

### Keyboard interactions

- `Enter` — Opens the option list or confirms selection
- `Space` — Opens the option list
- `ArrowDown` — Moves to the next option
- `ArrowUp` — Moves to the previous option
- `Tab` — Moves focus to the next focusable element

## API reference

### Importing

```css
@import 'luxen-ui/css/select';
```

### Attributes & Properties

- **data-size**: `xs | sm | md | lg | xl` — Control height on the shared `--l-size-control-*` scale (default `md`).
- **disabled** — Disables the select.
- **required** — Marks the field as required.
- **multiple** — Allows multiple selections.

### Events

- **change** — Fires when an option is selected.
- **input** — Fires when the value changes.

### CSS classes

- `.l-select` — Base select element with `appearance: base-select`.
- `.l-select-item` — Option styling with checkmark indicator.
- `.l-select-item-media` — Leading image/icon inside a rich option.
- `.l-select-item-text` — Column wrapper stacking title + description.
- `.l-select-item-title` — Primary label of a rich option.
- `.l-select-item-description` — Secondary line of a rich option (hidden in the trigger).

### CSS custom properties

- `--height` (default: `var(--l-form-control-height)`) — Control height (set via `data-size` or directly).
- `--border-radius` (default: `var(--l-form-control-border-radius)`) — Trigger border radius.
- `--caret-color` (default: `var(--l-form-control-placeholder-color)`) — Chevron color.
- `--caret-icon` (default: `mdi:chevron-down`) — Chevron mask image; override with any `url()` to re-skin.
