Usage
import { TagsInput } from '@kivora/react';
function Demo() {
const [tags, setTags] = useState<string[]>([]);
return (
<TagsInput
label="Topics"
value={tags}
onChange={setTags}
placeholder="Add topic..."
/>
);
}
Props
Controlled array of tag strings.
Default tags for uncontrolled mode.
Called when tags change. Receives the updated array of tags.
Label text displayed above the input.
placeholder
string
default:"'Add tag…'"
Placeholder text shown when no tags exist.
Error message to display below the input.
Disables the input and prevents tag management.
Maximum number of tags allowed.
Allow duplicate tags. When false, adding an existing tag is ignored.
splitChars
string[]
default:"['Enter', ',']"
Characters/keys that trigger tag creation.
size
'sm' | 'md'
default:"'md'"
Size variant affecting input and tag sizing.
Additional CSS classes to apply to the container.
HTML ID attribute. Auto-generated if not provided.
Examples
<TagsInput
label="Skills"
placeholder="Add skill..."
/>
function ControlledDemo() {
const [tags, setTags] = useState<string[]>(['React', 'TypeScript']);
return (
<TagsInput
label="Technologies"
value={tags}
onChange={setTags}
placeholder="Add technology..."
/>
);
}
<TagsInput
label="Top 3 Skills"
maxTags={3}
placeholder="Add up to 3 skills..."
/>
Allow Duplicates
<TagsInput
label="Keywords"
allowDuplicates
placeholder="Add keyword..."
/>
Custom Split Characters
<TagsInput
label="Email addresses"
splitChars={['Enter', ',', ';', ' ']}
placeholder="Add email..."
/>
Different Sizes
<TagsInput label="Small" size="sm" />
<TagsInput label="Medium" size="md" />
With Error State
function ValidatedTags() {
const [tags, setTags] = useState<string[]>([]);
return (
<TagsInput
label="Categories"
value={tags}
onChange={setTags}
error={tags.length === 0 ? 'At least one tag required' : undefined}
/>
);
}
Blog Post Tags Example
function BlogTagsInput() {
const [tags, setTags] = useState<string[]>([]);
const maxTags = 5;
return (
<div>
<TagsInput
label="Post Tags"
value={tags}
onChange={setTags}
maxTags={maxTags}
placeholder="Add tag and press Enter..."
error={tags.length > maxTags ? `Maximum ${maxTags} tags allowed` : undefined}
/>
<p className="text-xs text-muted-foreground mt-1">
{tags.length}/{maxTags} tags
</p>
</div>
);
}
Email Recipients
function EmailInput() {
const [recipients, setRecipients] = useState<string[]>([]);
const validateEmail = (email: string) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
return (
<TagsInput
label="To"
value={recipients}
onChange={setRecipients}
splitChars={['Enter', ',', ';', ' ']}
placeholder="Enter email addresses..."
/>
);
}
Keyboard Behavior
- Enter: Create tag from current input
- Comma (,): Create tag from current input (default)
- Backspace: Remove last tag if input is empty
- Blur: Create tag from current input if not empty
Notes
- Tags display as removable chips with × button
- Type text and press Enter or comma to add tag
- Click × on tag to remove it
- Backspace on empty input removes last tag
- Blur (unfocus) automatically adds pending input as tag
- Empty/whitespace-only tags are ignored
- Duplicate detection trims and compares tags
- When maxTags is reached, input becomes disabled
- Focus ring appears around entire container
- Chips size adjusts based on
size prop
- Click anywhere in container to focus input