TagsInput
Type a list of tags into one field: add, edit, delete and paste them from the keyboard.
Autofocus
autofocus through attrs puts the cursor in the input when the page loads, ready for the first tag.
Code
<TagsInput value={state.focusTags} placeholder="Add a label" attrs={{ autofocus: true }} />Usage
import { TagsInput } from "@elements/ui/tags-input";
<TagsInput value={post.tags} placeholder="Add a tag" attrs={{ "aria-label": "Tags" }} />
<TagsInput value={invite.emails} delimiter={/[,;\s]/} addOnPaste validate={isEmail} max={10} />Examples
Basic
Enter or a comma adds a tag. Backspace at the start highlights the last tag, a second Backspace deletes it. Arrows move the highlight; Enter or a double click edits.
Code
<TagsInput value={state.tags} inputValue={state.draft} placeholder="Add a fruit"
attrs={{ "aria-label": "Fruits" }} />Emails
A RegExp delimiter (comma, semicolon or space), paste as tags, and validate refusing what is not an email.
Code
<TagsInput value={state.emails} delimiter={/[,;\s]/} addOnPaste
validate={({ inputValue }) => /^\S+@\S+\.\S+$/.test(inputValue)} />Limits
max refuses a fourth tag and reports onValueInvalid with reason rangeOverflow; allowOverflow takes it and marks the field invalid. maxLength caps each tag.
Code
<TagsInput value={state.limited} max={3} onValueInvalid={(d) => state.invalid = d.reason} />
<TagsInput value={state.overflow} max={3} allowOverflow />
<TagsInput value={state.short} maxLength={5} />Disabled, read-only and invalid
Read-only tags can be highlighted but not changed.
Code
<TagsInput value={state.locked} disabled />
<TagsInput value={state.fixed} readonly />
<TagsInput value={state.wrong} invalid />Disabled tags
disabledTags keeps a tag in place: its delete button is disabled, Backspace and Delete skip it, it cannot be edited, and Clear leaves it.
Code
<TagsInput value={state.team} disabledTags={["owner"]} />On blur
blurBehavior add turns leftover text into a tag; clear drops it.
Code
<TagsInput value={state.added} blurBehavior="add" />
<TagsInput value={state.cleared} blurBehavior="clear" />Editing and sanitizing
editable={false} turns off edit mode. sanitizeValue lowercases here, with duplicates allowed.
Code
<TagsInput value={state.plain} editable={false} />
<TagsInput value={state.lower} sanitizeValue={(v) => v.trim().toLowerCase()} allowDuplicates />Set from code
value is two-way: push, assign or clear the array.
Code
<TagsInput value={state.tags} />
<Button onclick={() => state.tags.push("cherry")}>Add</Button>
<Button onclick={() => state.tags = ["one", "two"]}>Set</Button>
<Button onclick={() => state.tags = []}>Clear</Button>In a form
name submits the tags joined by commas; required blocks an empty list; reset restores.
Code
<form onsubmit={(e) => save(e)}>
<Field label="Skills" description="Press Enter after each one.">
<TagsInput value={state.skills} name="skills" required />
</Field>
<Button type="submit" variant="primary">Save</Button>
</form>With suggestions
suggestions offers options in a listbox under the input, as a combobox. Typing filters them, ArrowDown and ArrowUp highlight with focus kept in the input, Enter or a click adds the option, and chosen options are not offered again. Enter with nothing highlighted still adds the typed text.
Code
<TagsInput value={state.suggested}
suggestions={["Apple", "Lemon", "Pear", "Cherry", ...]}
placeholder="Add a fruit" attrs={{ "aria-label": "Fruits" }} />In a field
Field's label names the text input and its helper text and error describe it. A fourth skill sets error, which shows in its reserved line.
Add up to three.
Code
<Field label="Skills" description="Add up to three."
error={state.skills.length > 3 ? "Pick at most three skills." : ""}>
<TagsInput value={state.skills} invalid={state.skills.length > 3} />
</Field>Right to left
Under rtl the arrows swap with the layout. translations replace the button labels and the live-region messages.
Code
<div dir="rtl" lang="ar">
<TagsInput value={state.tags}
translations={{ clearTriggerLabel: "مسح كل الوسوم", deleteTagTriggerLabel: (v) => `حذف ${v}` }} />
</div>