Clawscale

Tag input

A TagInput collects a list of short values, such as regions, owners or table names, and shows each one as a Tag.

Usage#

import { TagInput } from "@clawscale/react";
<TagInput values={regions} onChange={(values) => setRegions(values.map(String))} />

TagInput is always controlled: pass values and update them in onChange, or in onAdd and onRemove. Enter adds the typed text. Backspace at the start of the field selects the last tag, and a second Backspace removes it.

Examples#

Basic#

onChange receives the full list after every add or remove. placeholder shows only while the list is empty.

eu-west-1us-east-1
import { TagInput } from "@clawscale/react";
import { useState } from "react";

export default function TagInputBasic() {
  const [regions, setRegions] = useState(["eu-west-1", "us-east-1"]);
  return (
    <TagInput
      inputProps={{ "aria-label": "Regions" }}
      placeholder="Add regions"
      values={regions}
      onChange={(values) => setRegions(values.map(String))}
    />
  );
}

Left icon#

leftIcon renders an icon before the tags.

data-platformfinance-analytics
import { TagInput } from "@clawscale/react";
import { useState } from "react";

export default function TagInputLeftIcon() {
  const [owners, setOwners] = useState(["data-platform", "finance-analytics"]);
  return (
    <TagInput
      inputProps={{ "aria-label": "Owner teams" }}
      leftIcon="people"
      placeholder="Add owner teams"
      values={owners}
      onChange={(values) => setOwners(values.map(String))}
    />
  );
}

Right element#

rightElement holds one element after the input, such as a minimal button that clears every tag.

orders_dailycustomer_profilesevents_raw
import { Button, TagInput } from "@clawscale/react";
import { useState } from "react";

const DEFAULT_DATASETS = ["orders_daily", "customer_profiles", "events_raw"];

export default function TagInputRightElement() {
  const [datasets, setDatasets] = useState(DEFAULT_DATASETS);
  const clearButton = (
    <Button aria-label="Clear datasets" icon="cross" variant="minimal" onClick={() => setDatasets([])} />
  );
  return (
    <TagInput
      inputProps={{ "aria-label": "Datasets" }}
      leftIcon="database"
      placeholder="Add datasets"
      rightElement={datasets.length > 0 ? clearButton : undefined}
      values={datasets}
      onChange={(values) => setDatasets(values.map(String))}
    />
  );
}

Tag props#

tagProps styles the tags. Pass an object for every tag, or a function to style each value on its own.

productionstagingdevelopment
import { TagInput } from "@clawscale/react";
import { useState } from "react";

export default function TagInputTagProps() {
  const [environments, setEnvironments] = useState(["production", "staging", "development"]);
  return (
    <TagInput
      inputProps={{ "aria-label": "Target environments" }}
      placeholder="Add environments"
      tagProps={(value) => (value === "production" ? { intent: "danger" } : { minimal: true })}
      values={environments}
      onChange={(values) => setEnvironments(values.map(String))}
    />
  );
}

Separators#

separator splits typed or pasted text into several tags. The default splits on commas and new lines. Set it to false to keep text whole.

import { TagInput } from "@clawscale/react";
import { useState } from "react";

export default function TagInputSeparator() {
  const [tables, setTables] = useState<string[]>([]);
  return (
    <TagInput
      inputProps={{ "aria-label": "Tables" }}
      placeholder="Paste table names separated by commas, semicolons or spaces"
      separator={/[,;\s]+/}
      values={tables}
      onChange={(values) => setTables(values.map(String))}
    />
  );
}

Interactive playground#

eu-west-1us-east-1ap-southeast-2
Props
Open dropdown
View source on GitHub

Props interface#

interface TagInputProps extends IntentProps, Props@clawscale/react
PropsDescription
addOnBlur
boolean = false
If true, onAdd will be invoked when the input loses focus. Otherwise, onAdd is only invoked when enter is pressed.
addOnPaste
boolean = true
If true, onAdd will be invoked when the user pastes text containing the separator into the input. Otherwise, pasted text will remain in the input.
autoResize
boolean = false
Whether the component should automatically resize as a user types in the text input. This will have no effect when fill={true}.
children
React.ReactNode = undefined
Optional child elements which will be rendered between the selected tags and the text input. Rendering children is usually unnecessary.
className
string
A space-delimited list of class names to pass along to a child element.
Inherited from Props
disabled
boolean = false
Whether the component is non-interactive. Note that you'll also need to disable the component's rightElement, if appropriate.
fill
boolean
Whether the tag input should take up the full width of its container.
inputProps
HTMLInputProps
React props to pass to the <input> element. Note that ref and key are not supported here; use inputRef below. Also note that inputProps.style.width will be overriden if autoResize={true}.
inputRef
React.Ref<HTMLInputElement>
Ref handler for the <input> element.
inputValue
string
Controlled value of the <input> element. This is shorthand for inputProps={{ value }}.
intent
Intent
Visual intent color to apply to element.
Inherited from IntentProps
largedeprecated
boolean = false
Whether the tag input should use a large size.
use size="large" instead.
leftIcon
IconName | MaybeElement
Name of a Blueprint UI icon (or an icon element) to render on the left side of the input.
onAdd
(values: string[], method: TagInputAddMethod) => boolean | void
Callback invoked when new tags are added by the user pressing enter on the input. Receives the current value of the input field split by separator into an array. New tags are expected to be appended to the list.
onChange
(values: React.ReactNode[]) => boolean | void
Callback invoked when new tags are added or removed. Receives the updated list of values: new tags are appended to the end of the list, removed tags are removed at their index.
onInputChange
React.ChangeEventHandler<HTMLInputElement>
Callback invoked when the value of <input> element is changed. This is shorthand for inputProps={{ onChange }}.
onKeyDown
(event: React.KeyboardEvent<HTMLElement>, index?: number) => void
Callback invoked when the user depresses a keyboard key. Receives the event and the index of the active tag (or undefined if focused in the input).
onKeyUp
(event: React.KeyboardEvent<HTMLElement>, index?: number) => void
Callback invoked when the user releases a keyboard key. Receives the event and the index of the active tag (or undefined if focused in the input).
onRemove
(value: React.ReactNode, index: number) => void
Callback invoked when the user clicks the X button on a tag. Receives value and index of removed tag.
placeholder
string
Input placeholder text which will not appear if values contains any items (consistent with default HTML input behavior). Use inputProps.placeholder if you want the placeholder text to _always_ appear.
rightElement
React.JSX.Element
Element to render on right side of input. For best results, use a small spinner or minimal button (button height will adjust if TagInput uses large styles). Other elements will likely require custom styles for correct positioning.
separator
string | RegExp | false = /[,\n\r]/
Separator pattern used to split input text into multiple values. Default value splits on commas and newlines. Explicit false value disables splitting (note that onAdd will still receive an array of length 1).
size
NonSmallSize = "medium"
The size of the tag input.
tagProps
TagProps | ((value: React.ReactNode, index: number) => TagProps)
React props to pass to each Tag. Provide an object to pass the same props to every tag, or a function to customize props per tag.
valuesrequired
readonly React.ReactNode[]
Controlled tag values. Each value will be rendered inside a Tag, which can be customized using tagProps. Therefore, any valid React node can be used as a TagInput value; falsy values will not be rendered.