// preview in
saved for every page

TagsInput

Several short values in one field, shown as removable chips. Use it for topics, labels, skills or email recipients, with or without a list of suggestions.

Built on Base UIPattern WAI-ARIA ComboboxClient componentSource ↗
minimal · light · #3fa34d
design systems
accessibility
allowCustom
disabled

Installation

Set up Camaleo once (Installation), then import it. Put it in a Field so the label names the input.

import { TagsInput, Field, FieldLabel, FieldDescription } from "@camaleo/react";

Anatomy

Chips and a text input share one box. Each chip has its own remove button, and suggestions open in a popup below.

design systems ✕accessibility ✕Add a topic
[data-slot="tags-input"][data-slot="tag"] · [data-slot="tag-remove"][data-slot="tags-input-input"]

Examples

Every example is a real file you can copy. They all wear the skin, mode and brand from the bar above.

minimal · light · #3fa34d
design systems
accessibility

Press Enter after each topic.

React

Pick from a list

Type "py". Without allowCustom only suggestions can be added, so every profile uses the same names and search finds them.

bug

Suggestions and new tags

Type a label that isn't listed and press Enter. emptyText tells people that Enter creates it, so they don't wait for a match.

Figma
React
TypeScript

3 / 5 skills

Limit and duplicates

Add "React" again, or a sixth skill. A repeated tag stays in the input without calling onValueChange, so catch it in onKeyDown; refuse the limit in onValueChange and say why in FieldError.

ana.souza@acme.com

Paste a list: commas, semicolons and line breaks split it.

Paste a list

Paste "joao@acme.com, lia@acme.com". An onPaste handler splits on commas and line breaks, so a column copied from a spreadsheet becomes one chip per address.

finance
Q3 report
board meeting

Backspace removes the last topic; ← moves to a topic, Delete removes it.

Remove with the keyboard

Focus the input and press Backspace, or ← and Delete. Each remove button is named after its tag through removeLabel, in the page's language.

bug
checkout

In a form

Click save. With name, every tag is submitted as its own value, so formData.getAll("labels") returns the list.

compliance
audit 2026

Locked while the quarterly audit runs, until 15 Nov.

Disabled, with a reason

disabled locks the chips and the input. Say in the description why and until when, or people will think it's broken.

In context

Tags live next to other fields. These are whole pieces of UI you can copy, in the skin you picked.

Invite people to Acme Design

They get an email with a link that expires in 7 days.

ana.souza@acme.com
marcus.lee@acme.com
Invite people by emailCard · Field · TagsInput · NativeSelect · Button

Article settings

performance
product

Up to 5. Readers can follow tags.

Article tagsCard · Field · Input · TagsInput · Switch · Button
Filter jobs
React
TypeScript
Job search filtersFieldset · Field · TagsInput · Checkbox · Button

Guidelines

bug
billing
mobile
DoOne spelling per tag.

Suggest the tags that exist, so filters and reports count them together.

Bug
bugs
BUG mobile
Don’tFree text with no suggestions.

People type the same tag three ways, and a filter for "bug" misses two of them.

onboarding
pricing
bug
DoOne or two words.

Short tags fit in a row and scan at a glance.

needs review before Friday
asked for annual discount
Don’tSentences as tags.

They fill the row, nobody can filter by them, and they belong in a comment.

Props

PropTypeDefaultDescription
valuestring[]—The tags, controlled.
defaultValuestring[][]The starting tags, uncontrolled.
onValueChange((value: string[]) => void)—Called with the whole new list when a tag is added or removed.
suggestionsstring[][]Offered in a popup as the user types; picking one adds it.
allowCustombooleanfalseEnter adds the typed text as a tag when no suggestion is highlighted. A tag already in the list is not added again: its text stays in the input and onValueChange is not called.
removeLabel(tag: string) => string(tag) => `Remove ${tag}`Accessible name of each chip's remove button (translatable).
emptyTextReactNode—Shown in the popup when no suggestion matches.
defaultOpenboolean—Opens the suggestions popup on first render.
disabledbooleanfalseWhether the component should ignore user interaction.

Other <input> attributes like placeholder, type, onKeyDown and onPaste go to the inline input.

Styling hooks

Restyle it without forking: target the attributes, or set the tokens on a parent, a skin or the field itself.

Attributes

data-slot"tags-input" · "tag" · "tag-remove" · "tags-input-input" · "combobox-popup" · "combobox-item"
data-highlightedon the chip or suggestion under the keyboard
data-popup-openon the input while suggestions are open
data-disabledpresent when disabled
data-invalidon the input inside an invalid Field

Tokens it reads

Color

--cml-border--cml-border-control--cml-danger--cml-fg--cml-fg-muted--cml-fg-secondary--cml-field-bg--cml-field-border-sides--cml-field-shadow--cml-focus-offset--cml-focus-ring--cml-focus-width--cml-item-highlight-fg--cml-item-highlight-shadow--cml-popover-bg--cml-popover-border--cml-shadow-popover--cml-surface-raised

Shape & size

--cml-border-width--cml-field-border-width--cml-field-height--cml-field-padding--cml-font-size-field--cml-gap--cml-item-height--cml-item-padding--cml-popover-border-width--cml-popover-padding--cml-radius-control--cml-radius-field--cml-radius-item--cml-radius-popover

Type & motion

--cml-duration-fast--cml-ease-standard--cml-font-control--cml-font-field--cml-motion-scale

This component only

--cml-corner-shape--cml-disabled-opacity--cml-item-divider--cml-item-highlight--cml-placeholder-style--cml-tag-border--cml-tag-fg--cml-tag-font-size--cml-tag-font-weight--cml-tag-height--cml-tag-letter-spacing--cml-tag-radius--cml-tag-text-transform

Accessibility

EnterAdds the highlighted suggestion, or the typed text with allowCustom. A tag already in the list stays in the input.
↓ / ↑Opens the suggestions and moves the highlight.
BackspaceIn the empty input, removes the last tag.
← / →Moves focus between the chips and back to the input.
Delete / BackspaceOn a focused chip, removes it.
EscCloses the suggestions.
Was this page helpful? · Edit this page on GitHub