Chip Input
Free-token entry — Enter or comma commits, delimited pastes split into chips, and per-chip validation keeps invalid entries visible instead of dropping them.
- Status
- Since
0.4.0- Accessibility pattern
- labelled token input
Last updated
Enter or comma commits; Backspace in the empty input removes the last chip.
Install
Add Chip Input from the VegaStack registry. The CLI verifies the item's integrity hash before writing it.
pnpm dlx shadcn@latest add @vegastack/chip-inputThe same command installs the registry items it composes: @vegastack/input, @vegastack/tag-group, @vegastack/use-announcer.
Usage
import { ChipInput } from "@/components/ui/chip-input";
<ChipInput aria-label="Tags" value={tags} onValueChange={setTags} />;ChipInput fills the gap neither existing component can:
TagGroup is a display list with no input, and
Combobox's value model is selection-from-items —
it cannot commit an arbitrary token. The field chrome is the Combobox input
group's, the chips are real Tags (24px remove targets included), and the
inner control is the real Input.
Scope
| Behaviour | Where it lives |
|---|---|
| Suggestions / autocomplete | A Combobox composition — deliberately not built in |
| Persisting the list | Host, via onValueChange |
| Chip colour semantics | Not here — Tag hue is decorative; invalid is the only state |
+N overflow collapse | TagGroup — display-list semantics, wrong for an editable field |
Examples
Per-chip validation
Entries are added and marked, not silently dropped: a pasted list of twenty
addresses with two typos shows twenty chips with two flagged
(data-invalid, destructive border) — and the field stays invalid until they
are fixed or removed.
Invalid entries stay visible and flagged — paste a list and fix the typos instead of losing them.
Sizes and states
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
allowDuplicates | boolean | false | Allow the same chip twice. When false, a duplicate entry is rejected and
announced. |
aria-label | string | — | Accessible name for the inner input. The control must never be unnamed. |
className | string | — | Extra classes for the field group root. |
defaultValue | string[] | [] | Initial chips for uncontrolled use. |
disabled | boolean | false | Disables the field and every chip's remove button. |
inputRef | React.Ref<HTMLInputElement> | — | Ref forwarded to the inner <input>. |
normalize | ((raw: string) => string) | (raw) => raw.trim() | Normalise a raw entry before it is committed (and before duplicate checking). The default trims whitespace. |
onValueChange | ((value: string[]) => void) | — | Fired with the next chip list on every add or remove. |
placeholder | string | — | Placeholder for the inner input while the field has room. |
ref | React.Ref<HTMLDivElement> | — | Ref forwarded to the group root <div> (data-slot="chip-input"). |
size | "lg" | "md" | "sm" | — | |
splitOn | RegExp | /[,\n]/ | Pattern the paste handler splits on, in addition to the Enter/comma commit keys. |
validate | ((chip: string) => boolean) | — | Per-chip validity. Invalid entries are still **added**, marked with
data-invalid on their chip, described as invalid for assistive tech, and
flip the whole field invalid until fixed or removed —
a pasted list keeps every entry visible instead of silently dropping the
malformed ones. |
value | string[] | — | Controlled chip list. Pair with onValueChange; omit for uncontrolled use. |
Data attributes and CSS variables on ChipInput
| Attribute | Values |
|---|---|
data-disabled | "" |
data-field-group | "" |
data-invalid | "" |
data-size | mirrors a prop or state value |
data-slot | "chip-input" |
Accessibility
- The inner input must carry an accessible name (
aria-label) — it is the control assistive tech interacts with. - Accepted, invalid, duplicate, and removed outcomes are announced through a polite live region; invalid chips also carry a text description, never colour alone.
- Every chip's remove button is named (
Remove …) with a 24px hit area (fromTag). - The field border reflects focus (
focus-withintint) and validity (data-invaliddestructive tint), matching the Combobox input group.
| Key | Action |
|---|---|
| Enter / , | Commit the draft as a chip. |
| Backspace (empty input) | Remove the last chip. |
| Tab | Move between the input and chip remove buttons. |
| Contract | States tested |
|---|---|
| Behaviour | empty, chips, invalid-chip, duplicate-rejected, disabled |
| Accessibility | keyboard, labeled, status-announcement, semantic-html |
| Visual | default, focus, invalid, disabled, dark |