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.
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.
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.
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.
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#
Props interface#
interface TagInputProps extends IntentProps, Props@clawscale/react| Props | Description |
|---|---|
addOnBlur | boolean = falseIf true, onAdd will be invoked when the input loses focus. Otherwise, onAdd is only invoked when enter is pressed. |
addOnPaste | boolean = trueIf 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 = falseWhether the component should automatically resize as a user types in the text input. This will have no effect when fill={true}. |
children | React.ReactNode = undefinedOptional child elements which will be rendered between the selected tags and the text input. Rendering children is usually unnecessary. |
className | stringA space-delimited list of class names to pass along to a child element. Inherited from Props |
disabled | boolean = falseWhether the component is non-interactive. Note that you'll also need to disable the component's rightElement, if appropriate. |
fill | booleanWhether the tag input should take up the full width of its container. |
inputProps | HTMLInputPropsReact 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 | stringControlled value of the <input> element. This is shorthand for inputProps={{ value }}. |
intent | IntentVisual intent color to apply to element. Inherited from IntentProps |
largedeprecated | boolean = falseWhether the tag input should use a large size. use size="large" instead. |
leftIcon | IconName | MaybeElementName of a Blueprint UI icon (or an icon element) to render on the left side of the input. |
onAdd | (values: string[], method: TagInputAddMethod) => boolean | voidCallback 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 | voidCallback 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) => voidCallback 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) => voidCallback 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) => voidCallback invoked when the user clicks the X button on a tag. Receives value and index of removed tag. |
placeholder | stringInput 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.ElementElement 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. |