DynamicTags
Always-visible input + tag flow: press Enter or a separator to create tags; supports deduplication, validation, limits, save-on-blur, reordering, overflow collapsing, and in-place tag editing.
Basic Usage
Deduplicate by default
model-value is a JSON array attribute; duplicate tags are not allowed by default. Keyboard: Enter / separator to submit; with the input empty, Backspace deletes the last tag.
Allow Duplicates
allow-duplicate
Separator & Paste Batching
separator=; (semicolon submits)
Paste comma-separated text to batch-create (on by default)
separatorcustomizes the commit separator (single character, default,; empty string = Enter only;separator=" "gives space triggering)add-on-paste(defaulttrue): pasting text that contains the separator splits and batch-creates tags, each going through dedup/limit/format checks; pastes without a separator keep native insertionmaxlengthlimits the input length
Save on Blur (Behavior Change)
save-on-blur defaults to true
save-on-blur=false discards on blur (old behavior)
Behavior change (since v2.5.0):
save-on-blurnow defaults totrue— leftover input text is committed as a tag on blur (aligning with the mainstream default). Previously the text was silently discarded; setsave-on-blur="false"explicitly to keep the old behavior.
Reordering
sortable: drag + buttons + keyboard reorder
sortable enables three reorder channels; a reorder dispatches oas-change (detail.trigger = "sort"):
- Buttons: per-tag "move up / move down" icon buttons swap with the neighbor on click (touch reachable — HTML5 drag is not available on touch screens)
- Drag: hold a tag and drop it on the target position
- Keyboard: with the input empty,
←focuses the last tag /→the first;←/→walk between tags (both ends return to the input);Alt + ←/Alt + →swap with the neighbor
On touch screens (pointer: coarse) tags grow to a 44px row height, and the remove / sort / clear button hit targets widen to 44px.
Overflow Collapsing
max-tag-count=2 collapses to +N
Tags beyond max-tag-count collapse into a +N counter with a title tooltip listing hidden tags; combine with oas-tooltip for richer display (attach the overlay to .tag-overflow after render).
Validation
pattern regex (digits only)
oas-before-add cancelable event (banned words)
pattern: a regex string; a mismatch rejects the add with a hint (reusing the duplicate-hint channel:aria-invalid+ a 2s message)oas-before-add: a cancelable event (detail: { value }); hosts callpreventDefault()to veto (synchronous validation only; async validation is not supported)- Check order: limit > format > duplicate >
oas-before-addveto
Editing Existing Tags
Double-click a tag to edit in place
Double-click a tag (or press Enter on a focused tag when sortable) to edit in place: Enter commits, Esc cancels, blur follows save-on-blur. Commits go through dedup/format checks; success dispatches oas-edit (detail: { index, value, oldValue }) and oas-change (trigger = "edit"); committing an empty value reverts.
Custom Tags
template[slot=tag]
template[slot="tag"] is cloned into each tag ([data-tag-label] binds the tag text; the remove button stays component-side). template[slot="prefix"] / template[slot="suffix"] clone to the start/end of the tag container.
Size / Status / Readonly / Clearable
size variants
status=error
readonly / clearable
readonly: tags stay, the input and remove buttons are hidden (form semantics differ from disabled)clearable: a clear button appears when there is a value and the component is interactive; clicking dispatchesoas-clearandoas-change(trigger = "clear")
IME Safety
While an IME composition is active (isComposing), pressing Enter or the separator (candidate confirmation) does not create a tag; pressing Enter after the composition ends commits normally. Safe for CJK input methods.
When to Use Select Multiple Instead
For "pick from suggestions + free input", use oas-select with multiple + searchable + allow-create (built-in suggestion dropdown, highlighting, multi-select chips) instead of building a dropdown over DynamicTags:
Select multiple + searchable + allow-create (comparison)
Rule of thumb: free-form short token sets (recipients, keywords) use DynamicTags; a candidate list that also accepts new values uses Select multiple.
max Limit
max=3
When max is reached, the input is automatically disabled; deleting a tag restores input.
Placeholder & Disabled
placeholder
disabled
Events
Add/remove/edit/clear/sort events
oas-change detail is { value, trigger } with trigger ∈ add | remove | clear | sort | edit (backward compatible: the value field is unchanged); there are also oas-add / oas-remove (detail: { value }), oas-edit (detail: { index, value, oldValue }), oas-clear, oas-before-add (cancelable), and oas-focus / oas-blur:
API
oas-dynamic-tags
Attributes
| Attribute | Description | Type | Default |
|---|---|---|---|
add-on-paste | Split pasted text into tags by separator (default true) | string | true |
allow-duplicate | Allow duplicate tags | boolean | — |
clearable | Clear button (one-click clears all tags) | boolean | — |
disabled | Disabled | boolean | — |
max | Maximum number of tags | string | — |
max-tag-count | Collapse overflow into a +N chip (title lists hidden tags) | number | — |
maxlength | Maximum length per tag | string | — |
model-value | Tag array (property or JSON) | string[] | [] |
pattern | Regex for new tags (mismatch warns and rejects) | string | — |
placeholder | Input placeholder | string | — |
readonly | Read-only (input/remove buttons hidden, tags display-only) | boolean | — |
save-on-blur | Commit leftover input as a tag on blur (default true, behavior change: previously silently discarded; set "false" for the old behavior) | string | true |
separator | Separator (creates a tag on type; default ,; empty string = Enter only) | string | , |
size | Size preset small / medium (default) / large | string | medium |
sortable | Tag sorting: drag + keyboard Alt+←/→ adjacent swap | boolean | — |
status | Validation status: error / warning / success | string | — |
Property (JS property; see each row for attribute reflection)
| Property | Description | Type | Default |
|---|---|---|---|
value | Current value: array of tag strings | string[] | [] |
Events
| Event | Description |
|---|---|
oas-add | Tag added, detail: { value } |
oas-before-add | Fires before creating a tag (cancellable via preventDefault; limit/format/duplicate checks run first), detail: { value } |
oas-blur | Fires when the input loses focus |
oas-change | Dispatched after add/remove, detail: { value } |
oas-clear | Fires on clear, detail: {} |
oas-edit | Tag edit committed, detail: { index, value, oldValue } (double-click or focused Enter to edit) |
oas-focus | Fires when the input gains focus |
oas-remove | Tag removed, detail: { value } |
Slots
| Name | Description |
|---|---|
template[slot="prefix"] | Prefix content slot |
template[slot="suffix"] | Suffix content slot |
template[slot="tag"] | Custom tag ([data-tag-label] binding; remove button stays component-side) |
CSS Variables
| CSS Variable | Default |
|---|---|
--oas-entry-pad | 0px |
Keyboard: Enter / , to submit; with the input empty, Backspace deletes the last tag.
ARIA: the container has role="list", tags have role="listitem", remove buttons are focusable with an aria-label; when submitting a duplicate, the input is marked aria-invalid with a hint shown.