Krizaka
Documentation

Tag input

Free words as removable chips — Enter or a comma adds one, a paste adds several, suggestions complete, normalize cleans and validate refuses with a reason.

WebBetaForms

Web only — React, from @krizaka/ui/tag-input. Beta: its API may still change in a minor version.

When to use

  • For keywords a person invents: the tags of a video, the topics of an article.
  • For a list of values typed one after the other: e-mail recipients, domains, IP addresses.

When not to use

  • When the values come from a closed list: a combobox with multiple.Use instead: Combobox
  • For one free value: a plain field.Use instead: Field

Installation

Install

npm install @krizaka/ui @krizaka/tailwind @krizaka/tokens tailwindcss

Styles

@import "tailwindcss";
@import "@krizaka/tailwind";
@import "@krizaka/ui/tailwind.css";

Import

import { TagInput } from "@krizaka/ui/tag-input";

Examples

Tags of a video

Suggestions, lower case without #, at most 10.

montrealsunset

Up to 10 tags, separated by commas.

E-mail recipients

validate refuses what is not an address; a comma or a space adds one.

ines@krizaka.com

Props

Words as removable chips — tags, keywords, e-mail recipients — with suggestions, cleaning and validation.

PropTypeDefaultDescription
labelrequiredstring—The visible label, passed translated (also the accessible name).
classNamestring—Classes merged on the root.
defaultValuereadonly string[][]The tags at first, uncontrolled.
disabledboolean—Not available.
errorstring—An error from the app (a server refusal); validate's own errors show here too.
hideLabelboolean—Hides the label visually, keeping it as the accessible name.
hintstring—A help text under the field ("Up to 10 tags, separated by commas").
labelsPartial<Pick<ComboboxLabels, "results" | "toggle" | "remove" | "empty" | "create">>—The words of the field, passed translated; English by default.
maxnumber—Most tags; the field stops offering more past it.
namestring—The name of the hidden inputs, for a plain <form> post (one per tag).
normalize((tag: string) => string)(tag) => tag.trim()Cleans a word before it is added ((t) => t.toLowerCase().replace(/^#/, "")). An empty result is ignored.
onValueChange((tags: string[]) => void)—Called with every tag after a change.
placeholderstring—The input's placeholder, passed translated.
separatorsreadonly string[][","]Keys that add the word, besides Enter. Default [","].
suggestionsreadonly string[][]Words offered as the person types (their own history, a curated list).
validate((tag: string, tags: readonly string[]) => string | null)—Refuses a word: return the reason (passed translated), shown and read as the field's error; null accepts it.
valuereadonly string[]—The tags (controlled).

Accessibility

  • Built on Combobox (multiple, creatable): the same combobox pattern and announcements.
  • A refusal from validate is shown under the field and read with it (aria-describedby, aria-invalid).
  • Each tag's remove button is named by labels.remove (“Remove sunset”).

Keyboard

KeysAction
Enter / ,Add the typed word as a tag (or the active suggestion).
BackspaceIn an empty input, remove the last tag.
Arrow Down / Arrow UpMove through the suggestions.

Best practices

  • Normalise the way the product stores tags (lower case, no #, no spaces) so “#Sunset” and “sunset” are one tag.
  • Say the limit and the separator in hint (“Up to 10 tags, separated by commas”).
  • Offer the person's own history first in suggestions, then a curated list.
  • Explain a refusal in words in validate (“Use letters and numbers only”).

Generated from the code of @krizaka/ui 2.4.0: its meta.ts, its examples and its types.Edit this documentation on GitHub

On this page