v1.0

Input Tag

Text field that turns typed entries into removable chips, inline within the field or in a group below it.

Pro
Design
Development
Project Management

Description

InputTag is a text field for collecting a list of short values (tags, topics, recipients, keywords). You type a value and commit it with Enter or a comma, and it becomes a removable chip. It is built on React Aria's TagGroup, so the chips get keyboard roving, Delete / Backspace removal on a focused chip, and the right ARIA semantics out of the box.

Two layouts share the same logic and state. inline (default) renders the chips inside the field, with the input flowing after them and wrapping onto new rows. outside keeps the field a single line and renders the chips in a group directly below it.

Reach for it when the number of values is open-ended and each value is a short label the user types. For picking from a known set of options, use a multi-select Select. For a single free-text value, use Input.

InputTag is a Create UI Pro component. With a Pro seat, add input-tag installs it into your project.

Installation

pnpm dlx @create-ui/cli add input-tag

Usage

import { InputTag } from "@/components/ui/input-tag"
const [tags, setTags] = React.useState<string[]>([])
 
<InputTag value={tags} onChange={setTags} placeholder="Add a tag..." />

Examples

Inline

Chips render inside the field and the input flows after them, wrapping onto new rows as the list grows. This is the default layout.

Pro
Design
Development
Project Management
Marketing
Invoicing
Research

Outside

The field stays a single line and the chips render in a group below it. Useful when the field sits in a dense form and you want the current selection summarized underneath.

Pro
Design
Development
Project Management
Marketing
Invoicing
Research

Autocomplete

Pass options to turn the field into a type-or-pick control. The list opens on focus and narrows as you type, and an option is hidden once it is added as a chip. Pressing Enter selects the exact match, or the top suggestion when there is no exact one, and creates the typed value only when nothing matches. A comma always creates the typed value, and the create footer is the explicit path to add a brand-new tag while suggestions are showing. Set createOnEnter to make Enter always create, and allowsCustomValue={false} for a pick-only control. Each option can carry a leading status dot (badge) and trailing meta.

Pro
UX Research

Sizes

Three sizes: xs, sm, and md (default). The field height, chip size, type scale, and radius all scale together. Inside a Field, the size cascades from the wrapper instead.

Pro
Design
Development
Project Management
Design
Development
Project Management
Design
Development
Project Management

Within a Field

Drop InputTag inside a Field to get a label and description. Size, invalid, disabled, and loading state cascade from the Field, so you set them once on the wrapper.

Pro
Topics
Design
Engineering

Press Enter or comma to add a topic. Backspace on an empty field removes the last one.

Max tags

max is a soft cap. Tags past the limit still commit, but they render in the error style and the whole field flips to the invalid treatment until the extras are removed. Remove a chip to bring the count back under the limit and the field recovers on its own.

Pro
Enter Your Categories
Design
Development
Project Management
Marketing
Invoicing
Research

Loading

Set isLoading while tags resolve on the server. The shell takes the busy treatment, a spinner replaces the text input in the same slot, and the chips mute and lose their remove buttons until loading ends.

Pro
Design
Development
Project Management

Accessibility

The chips are a React Aria TagGroup. Give the control an accessible name with aria-label, or wrap it in a Field with a FieldLabel.

KeyDescription
Enter ,Commits the typed text as a new tag.
BackspaceOn an empty input, removes the last tag.
ArrowLeft ArrowRightMoves focus between chips.
Delete BackspaceRemoves the focused chip.
  • Each chip exposes a remove button labelled for assistive technology.
  • The commit keys are configurable with delimiters.

Styling

Data slots: the component sets these for CSS targeting.

  • data-slot="input-tag" on the root (the field shell for inline, the column wrapper for outside).
  • data-slot="input-tag-group" on the TagGroup, data-slot="input-tag-list" on the TagList.
  • data-slot="input-tag-chip" on each chip, with data-slot="chip-label" and data-slot="chip-close" inside. Chips past the max limit also carry data-over-limit.
  • data-slot="input-tag-input" on the text input, data-slot="input-tag-spinner" on the loading spinner that replaces it.

API Reference

InputTag

Props

PropTypeDefaultDescription
valuestring[]-Controlled list of tags.
defaultValuestring[][]Uncontrolled initial list of tags.
onChange(value: string[]) => void-Fires with the full next list whenever a tag is added or removed.
onAdd(tag: string) => void-Fires with the single tag that was just added.
onRemove(tag: string) => void-Fires with the single tag that was just removed.
onCreate(tag: string) => void-Fires when a brand-new tag (not in options) is created.
optionsArray<string | InputTagOption>-Suggestions. Passing this enables the autocomplete dropdown.
allowsCustomValuebooleantrueAllow committing a value that is not in options.
filter(textValue, inputValue) => booleancontainsCustom match for the dropdown filter.
createOnEnterbooleanfalseEnter commits the typed text instead of selecting the top match.
emptyStateReact.ReactNodeNo resultsShown in the list when nothing matches and creating is disabled.
chips"inline" | "outside""inline"Where the chips render relative to the input.
size"xs" | "sm" | "md""md"Control size. Cascades from a wrapping Field when omitted.
chipSize"xs" | "sm" | "md" | "lg" | "xl"-Override the chip size the control size would otherwise derive.
maxnumber-Soft cap; tags past it render in the error style and flip the field invalid.
allowDuplicatesbooleanfalseAllow the same tag string more than once.
addOnBlurbooleanfalseCommit whatever is typed when the input loses focus.
delimitersstring[]["Enter", ","]Keys that commit the current input as a tag.
namestring-Renders a hidden input per tag for native form submission.
isDisabledbooleanfalseDisables the field. Cascades from a wrapping Field.
isInvalidbooleanfalseApplies the invalid treatment. Cascades from a wrapping Field.
isLoadingbooleanfalseBusy shell with an inline spinner in place of the input; chips mute.
placeholderstring-Placeholder for the text input.
classNamestring-Tailwind classes merged onto the root via cn().

InputTagOption

A bare string in options is shorthand for { value }.

PropTypeDescription
valuestringThe tag string committed when the option is picked.
labelReact.ReactNodeRow label; defaults to value. The chip shows value.
badgeStatusBadge colorLeading status-dot color for the row.
metaReact.ReactNodeTrailing meta, e.g. 24 uses.
isDisabledbooleanRenders the option non-selectable.