# Tag input (goodtabs UI)

Chips inside one input. Enter or a comma adds a tag, Backspace removes the last.

## Install

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

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

## Usage

```tsx
import { TagInput } from "@/components/ui/tag-input"

<TagInput aria-label="Tags" defaultValue={["react"]} max={5} onValueChange={setTags} />
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| value | `string[]` |  | Controlled tags. Leave out for an uncontrolled field. |
| defaultValue | `string[]` | `[]` | Starting tags for the uncontrolled form. |
| onValueChange | `(value: string[]) => void` |  | Fires with the new list after every add or remove. |
| placeholder | `string` | `"Add a tag"` | Shown in the empty input. |
| max | `number` |  | Most tags allowed. Shows a count and stops adding at the limit. |
| allowDuplicates | `boolean` | `false` | Keep tags that already exist, compared case-insensitively. |

## When to use

- Keywords, topics, skills, domains or emails: short values that pile up in one field
- Filters that people build up a term at a time
- Anywhere a comma-separated string would otherwise be typed by hand

## When not to use

- Picking from a fixed list: use a multi-select or a combobox
- Long values, sentences or anything that needs editing in place
- More than a dozen tags, where a list with its own layout reads better

## Notes for agents

- It takes a function (onValueChange), so a demo or page that passes one must be a client component
- The box is a div styled like shadcn's Input; className lands on it, every other prop lands on the inner input
- Give it an aria-label or an id that a Label points at; the chips have no label of their own
- Text left in the input is added on blur, so nothing typed is lost on submit

Docs: https://ui.goodtabs.co/components/tag-input