# Multi select (goodtabs UI)

Several picks shown as chips in a pill field, with a checked list in a popover.

## Install

```bash
npx shadcn@latest add https://ui.goodtabs.co/r/multi-select.json
```

Or, with the @goodtabs namespace configured in components.json: `npx shadcn@latest add @goodtabs/multi-select`

## Usage

```tsx
import { MultiSelect } from "@/components/ui/multi-select"

<MultiSelect
  options={[
    { value: "design", label: "Design" },
    { value: "frontend", label: "Frontend" },
  ]}
  defaultValue={["design"]}
  placeholder="Add tags"
  aria-label="Tags"
/>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| options | `{ value: string; label: string; disabled?: boolean }[]` |  | The choices, in order. |
| value | `string[]` |  | Controlled values. |
| defaultValue | `string[]` | `[]` | Initial values when uncontrolled. |
| onValueChange | `(value: string[]) => void` |  | Called with the new array. |
| placeholder | `string` | `"Select..."` | Field text when nothing is chosen. |
| maxChips | `number` | `3` | Chips shown before the rest collapse into +N. |
| searchable | `boolean` | `true` | Show the filter field above the list. |
| searchPlaceholder | `string` | `"Search..."` | Placeholder of the filter field. |
| disabled | `boolean` | `false` | Disables the field. |

## When to use

- Tags, labels, reviewers, channels: any set where several picks are normal
- Filters where the chosen values should stay visible in the field
- Lists long enough that typing to filter helps

## When not to use

- One pick only; use the searchable select
- Four options or fewer that fit on one line; use a checkbox list or toggle group
- Free text entries that are not in the list; use a tag input

## Notes for agents

- Works controlled (value, onValueChange) or uncontrolled (defaultValue); it takes functions, so render it from a client component
- The field is a focusable div with role combobox so chips can hold real remove buttons; Enter, Space or ArrowDown open it, Backspace removes the last pick
- Chips never wrap: the field stays 32px tall and folds extras into +N after maxChips
- The popover matches the field width and stays open while picking; the footer shows the count and clears everything

Docs: https://ui.goodtabs.co/components/multi-select