Skip to content

Headless tags input comparison

How @rozie-ui/tags compares to the existing tags / token / chips-input libraries across the six frameworks. Like the OTP, slider, and listbox families, the tags input has no shared vanilla-JS engine, and the landscape is overwhelmingly per-framework: every ecosystem grew its own token input (react-tag-input, @yaireo/tagify wrappers, vue3-tags-input, PrimeVue Chips / AutoComplete, ngx-chips, Angular Material MatChipGrid, …) with its own props, its own paste behaviour, and its own accessibility story. Rozie ships the same <Tags>, built on one native <input> plus a row of chips, with the same props, events, two-way tokens model, and handle, to all six frameworks.

Research snapshot: 2026-08-10. The tags-input landscape is fragmented and fast-moving; treat the library names, framework coverage, and feature columns as of that date.

The libraries at a glance

FrameworkRepresentative option(s)Paste-to-bulk-addTwo-way valuePer-token validationSame API, 6 fw
Reactreact-tag-input, react-tagsinput, @yaireo/tagify (React wrapper), Mantine TagsInput⚠️ value + onChange⚠️ varies
Vuevue3-tags-input, @sipec/vue3-tags-input, PrimeVue Chips/AutoComplete, Element Plus Tag + inputv-model⚠️
Sveltesvelte-tags-input, a handful of community chips inputs⚠️⚠️ bind⚠️
Solid(no mainstream dedicated option; hand-rolled)
Angularngx-chips, Angular Material MatChipGrid + input, PrimeNG Chips⚠️ CVA⚠️
Lit / web components(none mainstream)
Tagifyframework-agnostic vanilla engine (wrappers for React/Vue/Angular/jQuery)⚠️ per-wrapper⚠️ 3 fw via wrappers, no Svelte/Solid/Lit
Rozie@rozie-ui/tags-*r-model:modelValue (Angular CVA)validate

On its home framework each of these is a solid pick. The case for Rozie is consistency, coverage, and the no-engine native foundation: there is no tags component that spans every framework with the same API. Even the agnostic option, Tagify, is a vanilla engine you wrap per framework, and it reaches neither Svelte, Solid, nor Lit. Solid and Lit have no mainstream dedicated tags input at all. Rozie gives them all the same <Tags>, with no engine to ship.

No engine, native input + chips: the design choice

The deepest decision in a tags component is what holds the text and what holds the tokens. Two camps:

  • A vanilla engine owns the DOM (Tagify): a single library mounts into a container and renders the input + tags itself, mutating the DOM directly. Maximum features (drag-reorder, dropdown suggestions, inline edit) at the cost of a non-trivial engine dependency and a wrapper per framework that reconciles the engine's imperative state against the framework's.
  • A native <input> + framework-rendered chips (most per-framework libraries, Rozie): the typing surface is a real <input>; the chips are framework-rendered elements. Focus, the caret, the keyboard, and the clipboard come from the platform; the work is the choreography (commit on delimiter, bulk-add on paste, retreat on Backspace) and the dedup/validate/cap policy.

Rozie picks the no-engine native camp deliberately. The highest-value surface (the keyboard, paste, focus, mobile input) is the browser's, while Rozie owns the author-side API, the commit/dedup/validate logic, and the focus choreography. That choreography runs through one container ref, never per-chip refs, which is what gives it a clean cross-target story including Lit's shadow root. There is no engine to import and no required CSS.

Fully controlled tokens, one local draft

Most tags components keep an internal array of tokens and reconcile it against the bound value: a controlled/uncontrolled split with the usual footguns. @rozie-ui/tags keeps the committed tokens as modelValue (the sole model: true prop) and writes a fresh array back on every mutation. The only local state is the in-progress draft text in the input, a genuine UI buffer that is never the committed value. That is what lets the component stay fully controlled and two-way bound, and it is why the Angular output is a clean ControlValueAccessor (a tags input is a form control).

Feature matrix

Cell legend: = documented out-of-the-box · = not supported / not present · ⚠️ = partial / consumer-assembly-required.

CapabilityReact (react-tag-input)Vue (vue3-tags-input)Svelte (svelte-tags-input)Solid (none)Angular (ngx-chips)Lit (none)Tagify@rozie-ui/tags
Native <input> typing surface⚠️ engine input
Configurable delimiter keys⚠️delimiters
Paste-to-bulk-add⚠️
Backspace deletes previous⚠️
Dedup⚠️⚠️allowDuplicates
Per-token validation / normalize⚠️⚠️⚠️⚠️validate
Max cap⚠️⚠️max
Two-way value binding⚠️ value+onChangev-model⚠️ bind⚠️ CVA⚠️ per-wrapperr-model:modelValue (Angular CVA)
Custom chip rendering⚠️ render prop✅ slot⚠️✅ template⚠️ template fn✅ scoped #tag slot
Zero-config styling, re-skinnable⚠️⚠️⚠️⚠️⚠️✅ CSS-var tokens + shadcn/Material/Bootstrap bridges
Same API on all 6 frameworks⚠️ 3 fw via wrappers

Where Rozie wins today

  • First-class packages everywhere — including Solid and Lit, which have no mainstream tags input at all, and the same idiomatic surface on the frameworks Tagify's wrappers reach plus the ones they don't. These are categories the incumbents simply don't serve.
  • The same component surface everywhere. Where the ecosystem offers a different library per framework, @rozie-ui/tags is one <Tags> with the same props, the same add / remove / change events, the same two-way modelValue, and the same clear / focus handle. One component to learn, document, and migrate across your stack.
  • First-class validation + dedup + cap. validate (a normalize-or-reject function), allowDuplicates, and max are core props, not a feature you bolt on with an onChange interceptor.
  • A real two-way value. r-model:modelValue reads and writes the tokens with no onChange → setState glue, and because it is the sole model: true prop the Angular output is a ControlValueAccessor, so [formControl] / [(ngModel)] bind directly.
  • Zero-config styling that re-skins to any design system, and no engine to ship. Every rendered value is a --rozie-tags-* CSS custom property with a built-in fallback, plus ready-made token bridges for shadcn/ui, Material 3, and Bootstrap 5. There is no third-party engine dependency at all.

What Rozie defers

  • Autocomplete / suggestions dropdown. Tagify, PrimeVue AutoComplete, and Mantine pair the token input with a typeahead suggestion list. @rozie-ui/tags is a pure token input today; pair it with the Combobox or Listbox family for suggestions.
  • Inline token editing + drag-reorder. Tagify lets you double-click a chip to edit it and drag to reorder. Rozie models add/remove, not in-place edit or reorder.
  • Rich token objects. Several libraries support { id, label, … } token objects with per-token color/avatar. @rozie-ui/tags is a string[] model; render richness via the #tag slot, but the committed value is strings.
  • It's a single component, not a form/primitive kit. PrimeVue/PrimeNG, Angular Material, and Mantine ship chips alongside whole families of inputs and form controls. Rozie ships Tags (alongside its other @rozie-ui components), not a unified primitive suite.
  • @rozie-ui/tags is pre-1.0 and younger and less battle-tested than the established per-framework libraries. The full surface is documented in the API reference.

Try it

The @rozie-ui/tags showcase + API reference documents the @rozie-ui/tags-* packages: one pre-compiled, per-framework install (npm i @rozie-ui/tags-react, etc.). There is no engine to import and no required CSS: the native-input behaviour and a fully-tokenised skin ship inside the component, with optional one-line theme bridges for shadcn/ui, Material 3, and Bootstrap 5. The live demo runs the real Vue package in the page.

Cross-references

Pre-1.0 — APIs may change between minor versions.