# Combobox

Picks one value from a long list by typing to filter it: a country, a person, a repository. It has Input's box with a caret, and opens Select's list under the field; the arrow keys move through the matches and Enter picks one.

## Usage

### When to use

- Pick one value from a list too long to scan, by typing part of it: a country, a person, a repository.
- A list whose options the user already knows by name.

### When not to use

- A short list of options. Use Select, or RadioGroup to show them all.
- Free text. Use Input.
- Several values. Use Tokenizer, or Checkbox for a short list.

## Variants

### size

Field height from size-element-*. Match the Input or Button next to it: md in forms, sm only in dense mouse-first UI, lg or xl for the main field of a screen and on touch-first screens.

Values: `sm`, `md`, `lg`, `xl`. Default: `md`.

## Examples

### Country

```tsx
<Field className="w-full max-w-sm">
  <FieldLabel>Country</FieldLabel>
  <FieldControl>
    <Combobox placeholder="Search countries" emptyText="No country found.">
      <ComboboxItem value="de">Germany</ComboboxItem>
      <ComboboxItem value="jp">Japan</ComboboxItem>
      <ComboboxItem value="vn">Vietnam</ComboboxItem>
      <ComboboxItem value="us">United States</ComboboxItem>
    </Combobox>
  </FieldControl>
</Field>
```

### Groups

A heading over each group; a disabled option stays in the list but can't be picked.

```tsx
<Field className="w-full max-w-sm">
  <FieldLabel>Assignee</FieldLabel>
  <FieldControl>
    <Combobox defaultValue="ada" emptyText="No one found.">
      <ComboboxGroup heading="Design">
        <ComboboxItem value="ada">Ada Lovelace</ComboboxItem>
        <ComboboxItem value="grace">Grace Hopper</ComboboxItem>
      </ComboboxGroup>
      <ComboboxGroup heading="Engineering">
        <ComboboxItem value="alan">Alan Turing</ComboboxItem>
        <ComboboxItem value="edsger" disabled>Edsger Dijkstra</ComboboxItem>
      </ComboboxGroup>
    </Combobox>
  </FieldControl>
</Field>
```

## Do and don't

### Do

- Use it for lists too long to scan, where users know what they look for.
- Write emptyText that says what was not found: No country found.
- Put it in a Field with a visible label.

### Don't

- Don't use it for a short list; use Select or RadioGroup.
- Don't use it for free text; use Input.
- Don't use it for several values; use Tokenizer or Checkbox.

## Props

| Name | Type | Values | Default | Description |
| --- | --- | --- | --- | --- |
| `defaultValue` | `string` |  |  | The value picked on first render, when you don't control it. |
| `value` | `string` |  |  | The picked value, when you control it. Pair it with onValueChange. |
| `onValueChange` | `function` |  |  | Called with the value of the option the user picks. |
| `open` | `boolean` |  |  | Whether the list is open, when you control it. Pair it with onOpenChange. |
| `defaultOpen` | `boolean` |  | `false` | Opens the list on first render. |
| `onOpenChange` | `function` |  |  | Called with true or false when the list opens or closes. |
| `placeholder` | `string` |  |  | What to type, shown while the field is empty: Search countries. Not a label. |
| `emptyText` (required) | `string` |  |  | What the list says when the text matches no option: No country found. |
| `size` | `enum` | `sm`, `md`, `lg`, `xl` | `md` | Field height from size-element-*. Match the Input or Button next to it: md in forms, sm only in dense mouse-first UI, lg or xl for the main field of a screen and on touch-first screens. |
| `disabled` | `boolean` |  | `false` | Can't be focused or opened; the neutral disabled look. |
| `name` | `string` |  |  | Form name. The picked value is submitted under it. |

### Slots

| Name | Required | Description |
| --- | --- | --- |
| `items` | yes | ComboboxItem elements (value, the text, optional textValue and disabled), or ComboboxGroup elements with a heading around them. Keep them direct children. |

## Anatomy

| Part | Description |
| --- | --- |
| `root` | Combobox: the field and its list. |
| `group` | The field box: Input's sunken fill, control border, corners and sizes, with the text field and the caret. It shows the field's focus ring, disabled look and danger border. |
| `groupIcon` | Tabler CaretDown at the end, 16px (20px in xl), secondary. |
| `placeholder` | Placeholder text while nothing is picked or typed. |
| `content` | The list under the field, as wide as it: Select's raised surface. It scrolls past 288px. |
| `item` | An option, Select's option look: the md control height, inner corners, the neutral hover overlay when highlighted. |
| `indicator` | Tabler Check, 16px, at the end of the picked option. |
| `groupLabel` | The heading of a ComboboxGroup, Select's group heading. |
| `empty` | emptyText when nothing matches: 13px secondary text. |

## Accessibility

Role: `combobox`

| Keys | Action |
| --- | --- |
| `Type` | Filters the options to those that contain the text, and opens the list. |
| `ArrowDown, ArrowUp` | Opens the list, or moves through the matches; disabled options are skipped. |
| `Enter` | Picks the highlighted option and closes the list. |
| `Escape` | Closes the list and puts back the picked option's text. |
| `Tab` | Closes the list and moves on. |

- The field is a combobox with aria-expanded, aria-controls and aria-autocomplete="list"; the highlighted option is its aria-activedescendant, so focus stays in the field.
- Name it with a Field label or aria-label. The options are read with their selected state; a group is named by its heading.
- When no option matches, the list says emptyText.
- With name, the picked value is submitted under it in a hidden input.

## Install

```bash
npx shadcn add https://werewolf-ui.vercel.app/r/combobox.json
```

This also adds `styles/werewolf.css`, the tokens every component uses, and any other component it needs. Import that file once in your root CSS, after `@import "tailwindcss"`, with a path relative to that CSS file (from `app/globals.css` it is `@import "../styles/werewolf.css"`).
