Appearance
API reference
The full Tags surface: props, the two-way tokens model, change events, the imperative handle, and the scoped slot. For the per-framework consumption code see the usage page; for the live widget see the demo.
Props
The full prop surface. modelValue is the sole model: true prop — the committed tokens array — so the Angular output emits a ControlValueAccessor (a tags input is a form control). Boolean props default false (negative opt-out).
| Name | Type | Default | Two-way (model) | Required | Description |
|---|---|---|---|---|---|
modelValue | Array | [] | ✓ | The committed tokens — model: true, so a commit/remove/paste writes a fresh array back through r-model:modelValue (uncontrolled fallback []). Because it is the sole model prop, the Angular output is a ControlValueAccessor ([formControl] / [(ngModel)] bind directly). | |
delimiters | Array | […] | The keys that commit the current draft as a token (matched against the key event's key). Default [',', 'Enter']. Non-'Enter' entries also act as the split characters when pasting bulk text. Use e.g. [' ', 'Enter'] for a space-delimited input. | ||
allowDuplicates | Boolean | false | Allow the same token value to be added more than once. Defaults to false — a candidate equal (case-sensitive) to an existing token is silently rejected on commit. Set true to permit duplicates. | ||
max | Number | null | Maximum number of tokens. Once the list reaches max, the input is disabled and further adds (type, paste, programmatic) are rejected. null (the default) means unlimited. | ||
disabled | Boolean | false | Disable the whole control — the text input is disabled, every remove button is disabled, and no token can be added or removed. Also sets the Angular CVA disabled state. | ||
readonly | Boolean | false | Render the tokens read-only — they remain visible but cannot be added or removed, and the text input is hidden. Unlike disabled it carries no disabled styling, so it reads as a display of committed values. | ||
validate | Function | null | Optional per-token validator / normalizer. Called with (candidate, tokens) for each commit; return a (possibly normalized) string to accept it, or a falsy value (false / null / "") to reject the candidate. Runs before the dedup + max checks. Example: v => /^\S+@\S+$/.test(v) ? v.toLowerCase() : false for emails. | ||
placeholder | String | '' | Placeholder text for the inline text input (e.g. "Add a tag…"). | ||
ariaLabel | String | null | Accessible name for the whole control (role="group"). The inline text input is labelled with the same name so assistive tech announces what is being entered. A visually-hidden live region announces the current token count on change. |
Events
Every mutation of the committed list emits change (the new full array), so you can observe the list without two-way binding. Individual mutations also emit add / remove. A rejected candidate (duplicate, failed validate, or over max) emits nothing.
| Event | Description |
|---|---|
add | Fired when a token is committed (an accepted Enter / comma / paste add). Payload { value, tokens } — the newly added token string and the fresh full array. |
remove | Fired when a token is removed (a chip remove-button click or Backspace in an empty input). Payload { value, index, tokens } — the removed token, its former index, and the fresh full array. |
change | Fired on every committed-list mutation (add, remove, paste-bulk-add, or a programmatic clear). Payload { value } — the new full tokens array. |
Imperative handle
Declared once in the source via $expose; obtained through each framework's native ref mechanism.
| Method | Description |
|---|---|
clear | Remove every token (emits change with { value: [] }) and move DOM focus to the text input. Collision-safe — not a host-element member. |
focus | Move DOM focus to the inline text input. Deliberately named focus, which overrides the inherited HTMLElement.focus on the Lit custom element — the public focus() handle is the intended semantics (an accepted, warn-only ROZ137 on the Lit leaf). This mirrors the otp/slider precedent and is consistent with NumberField. |
Slots
| Slot | Params | Description |
|---|---|---|
tag | tag, index, remove | Scoped — fully replaces the rendering of each chip. tag is the token string, index its position, and remove() a zero-arg function that removes this token. The default fallback renders the built-in chip (label + remove button). On React the slot is a render-prop children callback (the documented cross-framework slot divergence). |
The slot name tag deliberately does not equal any prop key (ROZ127 — a slot/prop name collision is a hard error because Svelte 5 collapses snippets and props into one $props() bag).