Skip to content

Tags input

Removable tag chips with a hidden form value, max limit, paste parsing, and inline editing.

Primitive · form

Terminal window
npx shadcn@latest add https://ndigo.dev/r/tags-input.json

To use the shorter @ndigo/tags-input form, configure the namespace in components.json.

Source Target Type
registry/ui/tags-input/nd-tags-input.ts @ui/nd-tags-input/nd-tags-input.ts registry:ui
registry/ui/tags-input/nd-tags-input.css @ui/nd-tags-input/nd-tags-input.css registry:file

See this component rendered live on the live examples page.

Registry: Ndigo element foundation. Packages: @zag-js/tags-input@~1.47.0 (installed automatically).

<nd-tags-input> turns typed entries into chips. Enter or the delimiter adds a tag, the delete trigger removes one, and a hidden input carries the delimiter-joined form value ("alpha, beta" by default; the delimiter is configurable). Tags are editable by double-click or Enter on a highlighted chip.

<nd-tags-input name="skills" value="design, system">
<label data-part="label">Skills</label>
<div data-part="control">
<input data-part="input" placeholder="Add a skill" />
<button data-part="clear-trigger" type="button">Clear</button>
</div>
</nd-tags-input>

The element is the machine root. Items, previews, texts, delete triggers, and the editable item inputs are generated from the machine value and inserted before the authored input. A hidden input is created for the form value.

Attribute Type Description
value string Initial tags, comma-separated
name string Form field name for the hidden value
max number Maximum number of tags
delimiter string Add/split character (default ,)
placeholder string Input placeholder
add-on-paste boolean Split pasted text into tags
blur-behavior string add commits the typed tag on blur; clear drops it
disabled boolean Disable the control
readonly boolean Keep the value but block changes
invalid boolean Mark the control invalid
required boolean Mark the underlying input required
  • nd-value-change — detail: { value: string[] }. data-value mirrors the tags joined with ", " (the same format as the hidden input).
  • add(value) — add one tag, subject to max.
  • removeTag(value) — remove one tag by value.
  • clear() — remove every tag.

The visible input is labelled by the authored label. Enter or the delimiter adds the typed tag; Backspace at the start highlights and then deletes the last chip; Left/Right move between chips; Delete removes the highlighted chip; double-click or Enter on a highlighted chip edits it. The delete triggers carry per-tag aria-labels, and the hidden input keeps the form value.

Import nd-tags-input.css after the tokens. The control uses the surface and border tokens with an accent focus ring; chips use accent-soft, and the invalid state switches the control border to the danger token.