Tag Input
Free-text chips for keywords, recipients or labels. Backspace on an empty field removes the last tag, and pasting a comma-separated list splits it rather than making one long tag.
src/components/ui/tag-input.tsxAbout
From the component's own source, where it was written.
Free-text chips: keywords, recipients, labels.
Backspace on an empty field removes the last tag, which is the behaviour everyone expects from every mail client. It removes rather than "selects then removes" — the two-step version is more careful and nobody discovers it.
Pasting splits on the delimiters too, so pasting a comma-separated list gives a list of tags rather than one tag with commas in it.
Each chip's remove button is a real tab stop. A chip you can only delete by pointer is unremovable from the keyboard once you have tabbed past the field.
Install
npx astralyx-ui add tag-input
Usage
import { TagInput } from '@/components/ui/tag-input'
<TagInput value={tags} onValueChange={setTags} max={8} />Composer
Change the props and the source below follows.
<TagInput
defaultValue={['react', 'tailwind']}
max={6}
allowDuplicates={false}
/>Examples
Tags
<TagInput defaultValue={['react', 'tailwind']} max={6} />API
Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.
TagInput
Free-text chips: keywords, recipients, labels.
Extends Omit<ComponentProps<'div'>, 'defaultValue' | 'onChange'>.
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string[] | — | Controlled or uncontrolled. |
| defaultValue | string[] | [] | Controlled or uncontrolled. |
| onValueChange | (tags: string[]) => void | — | Controlled or uncontrolled. |
| placeholder | string | 'Add and press Enter' | — |
| delimiters | string[] | [',', 'Enter', 'Tab'] | Keys and characters that commit the current text. Tab only commits when there is something to commit, so an empty field still moves focus. |
| max | number | — | At the limit the field is disabled and says so. |
| allowDuplicates | boolean | false | At the limit the field is disabled and says so. |
| size | keyof typeof fieldSize | 'md' | — |
| variant | 'default' | 'secondary' | 'ghost' | 'default' | — |
| error | boolean | false | — |
| disabled | boolean | false | — |
| validate | (tag: string) => boolean | — | Reject an entry — an email shape, a length bound. |
Behaviour
| Topic | Detail | Description |
|---|---|---|
| removal | keyboard + pointer | Each chip has a real tab-stop remove button; a chip removable only by pointer is unreachable once you tab past the field. |