Highly customizable React component for inputing tags with keyboard shortcuts, validation, and render customization
npx @tessl/cli install tessl/npm-react-tagsinput@3.20.0React TagsInput is a highly customizable React component for creating tag input interfaces. It provides keyboard shortcuts, validation, render customization, and comprehensive event handling for building user-friendly tag selection systems.
npm install react-tagsinputimport TagsInput from 'react-tagsinput';
import 'react-tagsinput/react-tagsinput.css';For CommonJS:
const TagsInput = require('react-tagsinput');import React from 'react';
import TagsInput from 'react-tagsinput';
import 'react-tagsinput/react-tagsinput.css';
class Example extends React.Component {
constructor() {
super();
this.state = { tags: [] };
}
handleChange = (tags) => {
this.setState({ tags });
}
render() {
return (
<TagsInput
value={this.state.tags}
onChange={this.handleChange}
/>
);
}
}React TagsInput is built around a single main component with several key architectural patterns:
TagsInput class component providing all tag input functionalityrenderTag, renderInput, and renderLayout propsThe main React component for tag input functionality with extensive customization options.
class TagsInput extends React.Component {
constructor();
// Instance methods
focus(): void;
blur(): void;
accept(): boolean;
addTag(tag: string | object): boolean;
clearInput(): void;
}// Required props for TagsInput component
interface RequiredProps {
/** Array of current tags */
value: Array<string | object>;
/** Callback when tags change */
onChange(
tags: Array<string | object>,
changed: Array<string | object>,
changedIndexes: number[]
): void;
}interface BasicConfigProps {
/** CSS class for the wrapper element. Default: 'react-tagsinput' */
className?: string;
/** CSS class added when component is focused. Default: 'react-tagsinput--focused' */
focusedClassName?: string;
/** Keys that add a tag. Default: ['Tab', 'Enter'] */
addKeys?: Array<string | number>;
/** Keys that remove the last tag when input is empty. Default: ['Backspace'] */
removeKeys?: Array<string | number>;
/** Add tag when input loses focus. Default: false */
addOnBlur?: boolean;
/** Add tags when text is pasted. Default: false */
addOnPaste?: boolean;
/** Disable the component. Default: false */
disabled?: boolean;
}interface InputControlProps {
/** Set initial input value (uncontrolled mode) */
currentValue?: string;
/** Input value for controlled mode */
inputValue?: string;
/** Callback for input changes in controlled mode */
onChangeInput?(value: string): void;
/** Props passed to the input element */
inputProps?: {
className?: string;
placeholder?: string;
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;
onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;
[key: string]: any;
};
}interface ValidationProps {
/** Allow only unique tags. Default: false */
onlyUnique?: boolean;
/** Maximum number of tags allowed. Default: -1 (unlimited) */
maxTags?: number;
/** Custom validation function. Default: () => true */
validate?(tag: string): boolean;
/** Regex pattern for tag validation. Default: /.*/ */
validationRegex?: RegExp;
/** Callback when tags are rejected by validation */
onValidationReject?(rejectedTags: Array<string | object>): void;
}interface CustomizationProps {
/** Props applied to each tag element */
tagProps?: {
className?: string;
classNameRemove?: string;
[key: string]: any;
};
/** Property name for object tags display. Default: null (string tags) */
tagDisplayProp?: string;
/** Custom tag rendering function */
renderTag?(props: {
tag: string | object;
key: number;
disabled: boolean;
onRemove: (index: number) => void;
classNameRemove: string;
getTagDisplayValue: (tag: string | object) => string;
[key: string]: any;
}): React.ReactElement;
/** Custom input rendering function */
renderInput?(props: {
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
value: string;
addTag: (tag: string | object) => boolean;
[key: string]: any;
}): React.ReactElement;
/** Custom layout rendering function */
renderLayout?(
tagComponents: React.ReactElement[],
inputComponent: React.ReactElement
): React.ReactElement;
/** Function to split pasted text into tags */
pasteSplit?(data: string): string[];
/** Prevent form submission on Enter key. Default: true */
preventSubmit?: boolean;
}Pre-built rendering functions that can be used as references or extended.
/**
* Default tag rendering function
*/
function defaultRenderTag(props: {
tag: string | object;
key: number;
disabled: boolean;
onRemove: (index: number) => void;
classNameRemove: string;
getTagDisplayValue: (tag: string | object) => string;
}): React.ReactElement;
/**
* Default input rendering function
*/
function defaultRenderInput(props: {
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
value: string;
addTag: (tag: string | object) => boolean;
}): React.ReactElement;
/**
* Default layout rendering function
*/
function defaultRenderLayout(
tagComponents: React.ReactElement[],
inputComponent: React.ReactElement
): React.ReactElement;
/**
* Default paste splitting function - splits on spaces
*/
function defaultPasteSplit(data: string): string[];Methods available on TagsInput component instances for programmatic control.
/**
* Focus the input element
*/
focus(): void;
/**
* Blur the input element
*/
blur(): void;
/**
* Try to add whatever value is currently in the input element
* @returns true if a tag was successfully added
*/
accept(): boolean;
/**
* Add a specific tag programmatically
* @param tag - The tag to add (string or object)
* @returns true if the tag was successfully added
*/
addTag(tag: string | object): boolean;
/**
* Clear the current input value
*/
clearInput(): void;The component provides comprehensive event handling for user interactions:
The component supports two different tag storage modes:
String Tags (Default):
// Tags are stored as simple strings
const tags = ['react', 'javascript', 'web'];Object Tags:
// Tags are objects with a specified display property
const tags = [
{ id: 1, name: 'React', category: 'framework' },
{ id: 2, name: 'JavaScript', category: 'language' }
];
// Use tagDisplayProp to specify which property to display
<TagsInput
value={tags}
tagDisplayProp="name"
onChange={handleChange}
/>Two-tier validation system ensures data quality:
validate prop to implement custom logicvalidationRegex for pattern-based validationBoth validations must pass for a tag to be accepted. Rejected tags can be handled via the onValidationReject callback.
The component provides several CSS classes for styling customization:
/* Main wrapper - always present */
.react-tagsinput { }
/* Applied when component has focus */
.react-tagsinput--focused { }
/* Individual tag styling */
.react-tagsinput-tag { }
/* Tag remove button */
.react-tagsinput-remove { }
/* Input field styling */
.react-tagsinput-input { }All CSS classes can be overridden through the className, focusedClassName, tagProps, and inputProps configuration options.