# Select

## Overview

_[Design to fill]_

- **When to use**: _[Design to fill]_
- **When not to use**: _[Design to fill]_

## Anatomy

_[Design to fill]_

## Variants

| Prop         | Effect                                                                 |
| ------------ | ---------------------------------------------------------------------- |
| `multiple`   | Allows selecting several options; each option renders with a checkbox. |
| `isSmall`    | Renders a more compact trigger.                                        |
| `hasError`   | Applies the error style to the trigger to signal invalid input.        |
| `hasWarning` | Applies the warning style to the trigger to signal a caution state.    |

## Props / API

`Select` is a compound component built on Base UI's `Select`. Compose it from `Select.Trigger`, `Select.Menu`, and `Select.Option`.

### `Select`

| Prop         | Type                    | Default | Description                                                        |
| ------------ | ----------------------- | ------- | ------------------------------------------------------------------ |
| `options`    | `SelectOption<Value>[]` | -       | The list of selectable items backing the control.                  |
| `children`   | `React.ReactNode`       | -       | The compound sub-components (`Select.Trigger`, `Select.Menu`).     |
| `value`      | `Value[] : Value`       | -       | Controlled selected value (array when `multiple`).                 |
| `onChange`   | `(value) => void`       | -       | Called with the new value when the selection changes.              |
| `multiple`   | `boolean`               | `false` | Enables multi-selection; options render with a checkbox indicator. |
| `name`       | `string`                | -       | Name for the underlying form field.                                |
| `disabled`   | `boolean`               | `false` | Disables the whole control.                                        |
| `isSmall`    | `boolean`               | `false` | Renders a more compact trigger.                                    |
| `hasError`   | `boolean`               | `false` | Applies the error style to the trigger.                            |
| `hasWarning` | `boolean`               | `false` | Applies the warning style to the trigger.                          |

`Select` is generic over `Value` (the option value type) and `Multiple` (whether multi-select is enabled), so `value` and `onChange` are typed as arrays when `multiple` is set.

### `Select.Trigger`

The button that opens the menu and displays the current value.

| Prop         | Type                              | Default | Description                                                                                  |
| ------------ | --------------------------------- | ------- | -------------------------------------------------------------------------------------------- |
| `aria-label` | `string`                          | -       | Accessible name for the trigger when no visible label is associated.                         |
| `children`   | `(value: any) => React.ReactNode` | -       | Optional render function that formats the displayed value (e.g. a summary for multi-select). |

When `children` is omitted, the trigger shows the selected option's label. A chevron-down icon is always rendered at the end.

### `Select.Menu`

The floating popup.

| Prop       | Type              | Default | Description                           |
| ---------- | ----------------- | ------- | ------------------------------------- |
| `children` | `React.ReactNode` | -       | The `Select.Option` items to display. |

### `Select.Option`

A single selectable item.

| Prop       | Type              | Default | Description                                                                  |
| ---------- | ----------------- | ------- | ---------------------------------------------------------------------------- |
| `value`    | `Value \| null`   | -       | The value this option represents. Use `null` for a placeholder/empty option. |
| `children` | `React.ReactNode` | -       | The visible label content.                                                   |

In multi-select mode each option renders a read-only `Checkbox` indicator; in single-select mode the selected option shows a checkmark icon.

## States

- Default (idle)
- Hover
- Focus-visible
- Open/Expanded
- Selected
- Error
- Warning
- Disabled

## Code examples

```tsx
import { useState } from "react";
import { Select } from "@mylighthouse/prism-react";

const CITY_OPTIONS = [
  { value: null, label: "Select a city" },
  { value: "new-york", label: "New York" },
  { value: "los-angeles", label: "Los Angeles" },
];

export default function SelectExample(): React.JSX.Element {
  const [city, setCity] = useState<string | null>(null);

  return (
    <Select options={CITY_OPTIONS} value={city} onChange={setCity}>
      <Select.Trigger />
      <Select.Menu>
        {CITY_OPTIONS.map(({ value, label }) => (
          <Select.Option key={value} value={value}>
            {label}
          </Select.Option>
        ))}
      </Select.Menu>
    </Select>
  );
}
```

Multi-select with a formatted trigger summary:

```tsx
import { Select } from "@mylighthouse/prism-react";

const CITY_OPTIONS = [
  { value: "new-york", label: "New York" },
  { value: "los-angeles", label: "Los Angeles" },
  { value: "chicago", label: "Chicago" },
];

export default function SelectMultipleExample(): React.JSX.Element {
  return (
    <Select multiple options={CITY_OPTIONS}>
      <Select.Trigger>
        {(value: string[]) =>
          value.length === 0 ? "Select cities" : `${value.length} selected`
        }
      </Select.Trigger>
      <Select.Menu>
        {CITY_OPTIONS.map(({ value, label }) => (
          <Select.Option key={value} value={value}>
            {label}
          </Select.Option>
        ))}
      </Select.Menu>
    </Select>
  );
}
```

## A11y intent

_[Design to fill]_

- Built on Base UI's `Select`, so the trigger/listbox roles, expanded state, option selection state, and typeahead are handled correctly.
- The trigger opens with Enter/Space/arrow keys, options are navigable with the arrow keys and type-to-search, Escape closes the menu, and focus returns to the trigger on close.
- `hasError` / `hasWarning` are visual only, pair them with a programmatically associated message and don't rely on color alone to signal validity.
- The `disabled` control stays in the accessibility tree so its state is announced.

## Cross-references

_[Design to fill]_
