Skip to Content
⭐️ Leave a star →
ComponentsTagInput

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

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

PropTypeDefaultDescription
valuestring[]Controlled list of tags
defaultValuestring[][]Initial list (uncontrolled)
onChange(value: string[]) => voidCalled when tags are added or removed
disabledbooleanfalseDisables input + remove buttons
maxTagsnumberMaximum number of tags
allowDuplicatesbooleanfalseAllow duplicate values (case-sensitive)
commitKeysstring[]['Enter', ',']Keys that commit the current input as a tag
validate(tag, current) => booleanReturn false to reject the tag

Items props

Render-prop component that emits the current tags.

PropTypeDescription
children(tag, index, remove) => ReactNodeRender function for each tag

Field props

Accepts all standard <input> props except value, defaultValue, and onChange — TagInput manages those internally.

Data attributes

AttributeElementWhen present
data-disabledRootdisabled 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 validate or duplicates) are silently dropped.

Keyboard Interactions

KeyDescription
EnterCommits the current input as a tag (default commit key).
,Commits the current input as a tag (default commit key).
BackspaceWhen input is empty, removes the last tag.
Last updated on

MIT License © 2026 wire-ui

TagInput – Wire UI