# Select

## Overview

A styled dropdown for selecting a single option from a list. Built on Radix UI, it provides a fully accessible combobox with keyboard navigation, portaled content, and proper ARIA semantics. Always use `<Select>` from `xertica-ui` — never use native `<select>`.

---

## When to Use

- Choosing a single value from a list of 5+ options
- Role selection, category selection, status filters
- Period selectors in analytics dashboards

## When NOT to Use

- Binary choices — use `<Switch>` or `<RadioGroup>` instead.
- Multiple selection — use `<Checkbox>` groups.
- Fewer than 4 options that should all be visible — use `<RadioGroup>`.

---

## Anatomy

```
<Select>
  <SelectTrigger>
    <SelectValue placeholder="..." />
  </SelectTrigger>
  <SelectContent>
    <SelectItem value="...">Label</SelectItem>
    <SelectItem value="...">Label</SelectItem>
  </SelectContent>
</Select>
```

---

## Props

### Select

| Prop            | Type                      | Description                |
| --------------- | ------------------------- | -------------------------- |
| `value`         | `string`                  | Controlled selected value  |
| `defaultValue`  | `string`                  | Uncontrolled default value |
| `onValueChange` | `(value: string) => void` | Change handler             |
| `disabled`      | `boolean`                 | Disables the select        |

### SelectTrigger

| Prop          | Type                   | Default | Description                                                |
| ------------- | ---------------------- | ------- | ---------------------------------------------------------- |
| `size`        | `'sm' \| 'md' \| 'lg'` | `'md'`  | Size variant — matches Input sizing scale (h-8/h-10/h-12). |
| `className`   | `string`               | —       | Add width or style overrides                               |
| `placeholder` | `string`               | —       | Forwarded to `SelectValue`                                 |

### SelectItem

| Prop    | Type     | Required | Description      |
| ------- | -------- | -------- | ---------------- |
| `value` | `string` | **Yes**  | The option value |

---

## Examples

### Standalone

```tsx
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from 'xertica-ui/ui';

<Select>
  <SelectTrigger className="w-[180px]">
    <SelectValue placeholder="Select role" />
  </SelectTrigger>
  <SelectContent>
    <SelectItem value="admin">Administrator</SelectItem>
    <SelectItem value="editor">Editor</SelectItem>
    <SelectItem value="viewer">Viewer</SelectItem>
  </SelectContent>
</Select>;
```

### Controlled

```tsx
const [role, setRole] = useState('editor');

<Select value={role} onValueChange={setRole}>
  <SelectTrigger className="w-[200px]">
    <SelectValue />
  </SelectTrigger>
  <SelectContent>
    <SelectItem value="admin">Administrator</SelectItem>
    <SelectItem value="editor">Editor</SelectItem>
    <SelectItem value="viewer">Viewer</SelectItem>
  </SelectContent>
</Select>;
```

### Inside react-hook-form

```tsx
<FormField
  control={form.control}
  name="role"
  render={({ field }) => (
    <FormItem>
      <FormLabel>Role</FormLabel>
      <Select onValueChange={field.onChange} defaultValue={field.value}>
        <FormControl>
          <SelectTrigger>
            <SelectValue placeholder="Select a role" />
          </SelectTrigger>
        </FormControl>
        <SelectContent>
          <SelectItem value="admin">Administrator</SelectItem>
          <SelectItem value="editor">Editor</SelectItem>
        </SelectContent>
      </Select>
      <FormMessage />
    </FormItem>
  )}
/>
```

---

## AI Rules

- **Never** use native `<select>` — always use the full `<Select>/<SelectTrigger>/<SelectContent>/<SelectItem>` composition.
- **Sizing** — SelectTrigger defaults to `md` (h-10, 40px), matching Input's default. Use the same `size` prop across `Input`, `SelectTrigger`, `Textarea`, and `Search` to ensure consistent alignment in form rows.
- When used inside a form, wrap `<SelectTrigger>` in `<FormControl>` — the `field` spread goes on the `<Select>` (`onValueChange={field.onChange}`), not on the trigger.
- `SelectItem` requires a non-empty string `value` prop — never use empty strings or numbers.
- To set a default selected option, use `defaultValue` on `<Select>` — not on `<SelectItem>`.

---

## Related Components

- [`Form`](./form.md)
- [`RadioGroup`](./radio-group.md) — Alternative for small, always-visible option sets
- [`Checkbox`](./checkbox.md) — For multi-select scenarios
