Removable Tag List
A wrapping list of chips, each with a real remove button and an accessible label.
3 frameworksBeginner
A text field that turns typed values into removable chips, with the chips wrapping above the input.
<!--
The whole box is the input surface: focus-within lifts the ring so a chip row
plus a text field reads as one control. The chips wrap above the input rather
than pushing it off the right edge - min-w keeps the field usable once wrapped.
-->
<div class="w-full">
<label class="mb-1.5 block text-sm font-medium text-gray-700 dark:text-gray-300" for="tag-input">Tags</label>
<div class="flex flex-wrap items-center gap-2 rounded-lg border border-gray-300 bg-white p-2 focus-within:border-transparent focus-within:ring-2 focus-within:ring-blue-600 dark:border-gray-700 dark:bg-gray-900 dark:focus-within:ring-blue-400">
<span class="inline-flex items-center gap-1 rounded-full bg-gray-100 py-1 pl-2.5 pr-1 text-sm font-medium text-gray-700 dark:bg-gray-800 dark:text-gray-200">
Design
<button type="button" aria-label="Remove Design" class="inline-flex h-5 w-5 items-center justify-center rounded-full text-gray-400 transition-colors hover:bg-gray-200 hover:text-gray-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 dark:hover:bg-gray-700 dark:hover:text-gray-100 dark:focus-visible:ring-blue-400">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" class="h-3.5 w-3.5" aria-hidden="true"><path d="m6 6 12 12M18 6 6 18" /></svg>
</button>
</span>
<input id="tag-input" type="text" placeholder="Add a tag…" class="min-w-[8rem] flex-1 border-0 bg-transparent p-1 text-sm text-gray-900 outline-none placeholder:text-gray-500 dark:text-gray-100 dark:placeholder:text-gray-400" />
</div>
</div>| Prop | Type | Default | Description |
|---|---|---|---|
labelrequired | string | - | Accessible label announced while loading. |
defaultTags | string[] | [] | Default tags |
placeholder | string | 'Add a tag…' | Placeholder |
max | number | - | Max |
onChange | (tags: string[]) => void | - | On change |
className | string | - | Additional classes merged onto the root element. |
Enter or a comma commits a chip and Backspace on an empty field removes the last; entries are de-duped case-insensitively and `max` caps the count. Removing a chip returns focus to the input so a keyboard user is never stranded on a button that just unmounted.