Tag Input
Type, paste or backspace your way through a row of glowing chips.
Built on Icons.
Installation
npx shadcn@latest add https://neonkit.heyaadi.com/r/tag-input.jsonUsage
import { TagInput } from "@/components/ui/tag-input"
<TagInput
label="Skills"
placeholder="Add a skill"
defaultValue={["TypeScript", "Rust"]}
/>Examples
Suggestions
suggestions opens a small list that filters as you type and skips tags already added.
Custom separators
separators takes keys or characters. Here a space commits too, and a pattern keeps topics URL-safe.
Sizes, error and disabled
API reference
Also accepts native input attributes, and the ref points at the input. className and style go to the field box.
| Prop | Type | Default |
|---|---|---|
value | string[]Controlled tags. | None |
defaultValue | string[]Initial tags when uncontrolled. | None |
onValueChange | (value: string[]) => voidCalled when tags are added or removed. | None |
placeholder | stringShown while there are no tags. | None |
max | numberMost tags allowed. Extra ones are turned away with a message. | None |
separators | string[]Keys that commit the typed text: "Enter", "Tab", or single characters like "," and " ". | [",", "Enter"] |
validate | (tag: string) => trueReturn true to accept, or a message to show. Rejected text stays in the input. | None |
allowDuplicates | booleanAccept a tag that's already there. Duplicates are compared case-insensitively. | false |
suggestions | string[]Offered in a list that filters as you type. | None |
name | stringSubmits each tag under this name with a surrounding form. A form reset puts back the starting tags. | None |
required | booleanSatisfied by at least one tag; the empty text box after a commit doesn't count against it. | false |
label | ReactNodeVisible label for the input. | None |
description | ReactNodeHelper text under the field. Replaced by any error. | None |
error | ReactNodeRed invalid state and message. Pass true for the state without a message. Validation messages take precedence. | None |
disabled | booleanBlocks editing and leaves the tags out of form data. | false |
color | NeonColorPalette name or hex. Falls back to --neon-accent, then cyan. | inherited |
size | "sm"Minimum field height and chip size. | "md" |
containerClassName | stringClasses for the outer block with the label, field and message. | None |
Accessibility
- When the browser rejects the field on submit (required, type, pattern), it turns red until it's edited or the form resets. The browser shows its own message.
- A separator key commits the typed text. Pasting splits on commas, newlines and any character separators, and the field commits what's typed when you leave it.
- Backspace in an empty input lights up the last chip; a second Backspace removes it. Any other key cancels.
- ArrowLeft from the start of an empty input moves onto the chips. ArrowLeft and ArrowRight move between them, Home goes to the first, End or Escape returns to the input.
- On a focused chip, Backspace removes it and moves left; Delete removes it and moves right. Typing returns to the input with the character.
- With suggestions, the input is a combobox: ArrowUp and ArrowDown move through the list, Enter picks, Escape closes.
- Rejections set aria-invalid and show their reason in place of the description. Additions, removals and rejections are announced through a polite live region.
- The shake and the power-on flicker are skipped under prefers-reduced-motion.