Tag input
Also called chip input, tags input, or token field
A text field where each word you type becomes a removable chip when you press Enter or a comma, for adding labels, emails, or keywords.
import { useState } from 'react';
import { motion } from 'motion/react';
type Props = { tags: string[]; onChange: (tags: string[]) => void };
export function TagInput({ tags, onChange }: Props) {
const [draft, setDraft] = useState('');
function add(text: string) {
const all = [...tags, ...text.split(',').map((part) => part.trim())];
const lower = all.map((tag) => tag.toLowerCase());
// Skip blanks and repeats, ignoring case; the first spelling wins.
onChange(all.filter((tag, i) => tag && lower.indexOf(lower[i]!) === i));
setDraft('');
}
return (
<div className='flex w-96 flex-wrap items-center gap-1.5 rounded-lg border bg-background p-1.5 focus-within:ring-2 focus-within:ring-ring'>
{tags.map((tag) => (
// New chips scale in; `layout` slides the others over when one is removed.
<motion.span
key={tag}
layout
initial={{ scale: 0.8, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
className='flex items-center gap-1 rounded-md bg-muted py-1 pr-1 pl-2 text-sm'
>
{tag}
<button
type='button'
aria-label={`Remove ${tag}`}
onClick={() => onChange(tags.filter((t) => t !== tag))}
className='rounded px-1 text-muted-foreground hover:text-foreground'
>
×
</button>
</motion.span>
))}
<input
aria-label='Tags'
value={draft}
placeholder={tags.length ? '' : 'Add a tag'}
// A comma, typed or pasted, turns the text before it into chips.
onChange={(event) =>
event.target.value.includes(',')
? add(event.target.value)
: setDraft(event.target.value)
}
onKeyDown={(event) => {
if (event.key === 'Backspace' && !draft) onChange(tags.slice(0, -1));
if (event.key !== 'Enter') return;
event.preventDefault(); // keep Enter from submitting the form
add(draft);
}}
className='h-8 min-w-24 flex-1 bg-transparent px-1 text-sm outline-none'
/>
</div>
);
}Build a tag input for post tags: typing a word and pressing Enter or comma turns it into a rounded chip with an × button, Backspace in the empty input removes the last chip, and duplicates are ignored regardless of case. New chips scale in from 0.8 over 150ms, the field wraps onto new lines as it fills, and up to 5 matching existing tags are suggested below the input.
Paste into Layerwise or any AI coding tool.
What is Tag input?
A tag input looks like a normal text field, but each entry turns into a small chip inside the field when you press Enter or type a comma. Each chip has an × to remove it, and pressing Backspace in the empty field removes the last one. The field wraps onto a new line as the chips fill it.
Use it when people enter several short values of the same kind: tags on a post, recipients of an email, skills on a profile, keywords for a filter. Suggest existing tags as people type, so everyone reuses one spelling, such as “design”.
Trim spaces, ignore duplicates, and let people paste a comma-separated list in one go. Make every chip’s remove button reachable with the keyboard and give it a label such as “Remove design”.
Often confused with
Related terms
All termsCombobox
A text field with a dropdown list that filters as you type, so people can pick one option from a long list quickly.
Badge
A small rounded label that marks a status or a count, like New, Beta, Failed, or the red number on an inbox icon.
Pop in
An entrance animation where an element scales up past its full size and settles back, giving it a quick, springy arrival.
Layout animation
An animation that smoothly moves and resizes elements when the layout changes, such as list items gliding to new spots after a sort or filter.
Build it with Layerwise
Describe your app, watch it run in a live preview, and publish it with a database, storage, and sign-in built in.