TagInput
Multi-tag input. Press Enter or comma to add a tag; Backspace at an empty input removes the last tag. Tags are rendered via a render-prop so you bring your own UI (commonly using Tag).
Features
Commit keys are configurable (defaults to Enter and comma).
Optional validator and maxTags limit.
Duplicate rejection (case-sensitive) toggleable.
Backspace at empty input removes the last tag.
Can be controlled or uncontrolled.
Example
reacttailwind
2/5 — press Enter or comma to add
Anatomy
import { TagInput, Tag } from '@wire-ui/react'
<TagInput.Root defaultValue={['react', 'tailwind']}>
<TagInput.Items>
{(tag, i, remove) => (
<Tag.Root key={`${tag}-${i}`}>
<Tag.Label>{tag}</Tag.Label>
<Tag.Remove onClick={remove}>×</Tag.Remove>
</Tag.Root>
)}
</TagInput.Items>
<TagInput.Field placeholder="Add a tag…" />
</TagInput.Root>Styling
Root exposes data-disabled. Use focus-within: to style the wrapper when the inner input has focus.
<TagInput.Root className="
focus-within:ring-2 focus-within:ring-black
data-[disabled]:opacity-50
">
...
</TagInput.Root>Using data attributes
Root sets data-disabled when disabled. The Field is auto-disabled when maxTags is reached.
[data-disabled] { opacity: 0.5; }
:has(> input:focus) .wrapper { /* focus-within styling */ }Root props
| Prop | Type | Default | Description |
|---|---|---|---|
value | string[] | — | Controlled list of tags |
defaultValue | string[] | [] | Initial list (uncontrolled) |
onChange | (value: string[]) => void | — | Called when tags are added or removed |
disabled | boolean | false | Disables input + remove buttons |
maxTags | number | — | Maximum number of tags |
allowDuplicates | boolean | false | Allow duplicate values (case-sensitive) |
commitKeys | string[] | ['Enter', ','] | Keys that commit the current input as a tag |
validate | (tag, current) => boolean | — | Return false to reject the tag |
Items props
Render-prop component that emits the current tags.
| Prop | Type | Description |
|---|---|---|
children | (tag, index, remove) => ReactNode | Render function for each tag |
Field props
Accepts all standard <input> props except value, defaultValue, and onChange — TagInput manages those internally.
Data attributes
| Attribute | Element | When present |
|---|---|---|
data-disabled | Root | disabled prop is true |
Accessibility
- The Field is a regular
<input type="text">— pair it with an external<label>for an accessible name. - Removing a tag via the render-prop’s
remove()keeps focus available on the Field for fast bulk editing. - Invalid entries (rejected by
validateor duplicates) are silently dropped.
Keyboard Interactions
| Key | Description |
|---|---|
| Enter | Commits the current input as a tag (default commit key). |
| , | Commits the current input as a tag (default commit key). |
| Backspace | When input is empty, removes the last tag. |
Last updated on