Introducing PrimeReact v11-alpha 🎉Discover Now

InputTags

An unstyled tag input component with keyboard navigation, delimiter support, and optional typeahead suggestions.

Build fully custom tag input fields with complete control over layout and styling.

basic-demo

Pre-styled Versions

Choose a pre-styled library to use InputTags with ready-made designs.
For hook-based usage without components, see the Headless API.

Features#

  • Tag creation on Enter key press with optional delimiter character
  • Maximum tag limit with max prop
  • Duplicate prevention with allowDuplicate
  • Optional typeahead suggestions by composing AutoComplete.Root inside InputTags.Control
  • Add and remove event callbacks for fine-grained control
  • Paste support with addOnPaste and automatic delimiter splitting

Usage#

import { InputTags } from 'primereact/inputtags';
<InputTags.Root value={tags} onValueChange={(e) => setTags(e.value)}>
    <InputTags.Items>
        {({ item, remove }) => (
            <span>
                {item}
                <button onClick={remove}>×</button>
            </span>
        )}
    </InputTags.Items>
    <InputTags.Control>{({ controlProps }) => <input {...controlProps} />}</InputTags.Control>
</InputTags.Root>

InputTags.Items is a pure render-prop iterator: it invokes children once per tag with { item, index, remove, itemProps }. Spread itemProps onto the rendered chip element to wire ARIA roles and the data-selected focus marker. InputTags.Control calls children exactly once with { controlProps, add, remove, removeLast, removeAll, value, inputValue, focused }. add accepts either a single string or an array of strings.

With Typeahead#

For suggestion-driven tag entry, mount an <AutoComplete.Root> tree inside <InputTags.Control>. Spread controlProps onto <AutoComplete.Input> so the text-entry gets InputTags' Backspace-to-remove, delimiter-split, addOnBlur / addOnPaste, and focus handlers. On AutoComplete.onValueChange (option selection), call add from the render-prop arg to commit the tag. Attach a callback ref + state to <InputTags.Root> and pass that element to <AutoComplete.Positioner anchor={...}> so the suggestion popup sizes against the full chip-input field rather than just the typing area.

import { AutoComplete } from 'primereact/autocomplete';
import { InputTags } from 'primereact/inputtags';
 
const [rootEl, setRootEl] = React.useState<HTMLElement | null>(null);
 
<InputTags.Root ref={setRootEl} value={tags} onValueChange={(e) => setTags(e.value)}>
    <InputTags.Items>
        {({ item, remove, itemProps }) => (
            <span {...itemProps}>
                {item}
                <button onClick={remove}>×</button>
            </span>
        )}
    </InputTags.Items>
    <InputTags.Control>
        {({ controlProps, add }) => (
            <AutoComplete.Root
                options={filteredItems}
                onComplete={onSearch}
                onValueChange={(e) => {
                    if (typeof e.value === 'string') add(e.value);
                }}
            >
                <AutoComplete.Input {...controlProps} />
                <AutoComplete.Portal>
                    <AutoComplete.Positioner anchor={rootEl}>
                        <AutoComplete.Popup>
                            <AutoComplete.List />
                            <AutoComplete.Empty>No results found</AutoComplete.Empty>
                        </AutoComplete.Popup>
                    </AutoComplete.Positioner>
                </AutoComplete.Portal>
            </AutoComplete.Root>
        )}
    </InputTags.Control>
</InputTags.Root>;

Behavior#

Polymorphic Root#

Use as on InputTags.Root to change the rendered HTML element.

<InputTags.Root as="section">...</InputTags.Root>

Render Prop Architecture#

The component intentionally has no Item / Label / Remove / Input sub-parts. Consumers compose the per-tag JSX (e.g. Chip.*, Tag, custom) inside InputTags.Items, and the text-entry element (a plain <input>, <AutoComplete.Input>, or anything else) inside InputTags.Control.

Pass Through#

Some parts may not be visible in the preview depending on the component's current state.

Loading...
/* Select a part to see its CSS selector for custom styling */

API#

InputTagsRoot#

NameTypeDefault
refRef<unknown>—
The reference to the component instance.
pIfbooleantrue
Whether the component should be rendered.
styleCSSProperties | ((instance?: InputTagsRootInstance) => CSSProperties)—
The style to apply to the component.
classNamestring | ((instance?: InputTagsRootInstance) => string)—
The class name to apply to the component.
asstring | number | bigint | boolean | ComponentClass<any, any> | FunctionComponent<any> | ReactElement<unknown, string | JSXElementConstructor<any>> | Iterable<ReactNode, any, any> | ReactPortal | Promise<AwaitedReactNode>—
The component type to render.
asChildbooleanfalse
Whether the component should be rendered as a child component.
instanceInputTagsRootInstance—
The instance to pass to the component.
ptSafeRecord<InputTagsRootPassThrough>—
The pass-through props to pass to the component.
ptOptionsPassThroughOptions—
The pass-through options to pass to the component.
unstyledboolean—
Whether the component should be rendered without classes.
dtunknown—
The design token to use for the component.
stylesStylesOptions<ComponentInstance>—
The styles to use for the component.
render(instance: InputTagsRootInstance) => ReactNode—
The render function to render the component with instance access.
childrenany—
The children to render. Accepts `React.ReactNode` for static content or a render function `(instance: I) => React.ReactNode` for instance access. Typed as `any` to avoid JSX type errors when used directly in templates.
valuestring[]—
Controlled list of tag values.
defaultValuestring[]—
Initial tag values for uncontrolled usage.
inputValuestring—
Controlled value of the text-entry control.
defaultInputValuestring—
Initial value of the text-entry control for uncontrolled usage.
maxnumber—
Maximum number of tags that can be added.
delimiterstring | RegExp—
Delimiter used to split typed or pasted text into tags.
allowDuplicateboolean—
Whether duplicate tag values are allowed.
addOnBlurboolean—
Whether the current input value should be added when the control loses focus.
addOnPasteboolean—
Whether pasted text should be added as tags.
addOnTabboolean—
Whether the current input value should be added when tabbing away.
onAdd(event: useInputTagsAddEvent) => void—
Callback fired after a tag is added.
onRemove(event: useInputTagsRemoveEvent) => void—
Callback fired after a tag is removed.
onInputValueChange(event: useInputTagsInputValueChangeEvent) => void—
Callback fired when the text-entry value changes.
disabledboolean—
When present, it specifies that the component should be disabled.
namestring—
Name of the input element.
invalidboolean—
When present, it specifies that the component should have invalid state style.
variant"outlined" | "filled"—
Specifies the input variant of the component.
fluidboolean—
When enabled, the component spans the full width of its parent.
onValueChange(event: InputTagsRootValueChangeEvent) => void—
Callback fired when the inputtags's value changes.
[key: string]any—
pt-{optionName}-*-—
Pass through attributes for customizing component. For more info, see Pass Through tab.
AttributeValue
data-scope"inputtags"
data-part"root"

Defines passthrough(pt) options of InputTags component.

labeltypedescription
rootInputTagsRootPassThroughType<HTMLAttributes<HTMLDivElement>>Used to pass attributes to the root's DOM element.

InputTagsItems#

InputTagsItems accepts a render-prop child invoked once per tag with { item, index, remove, itemProps }. Spread itemProps onto the rendered chip element for ARIA + keyboard navigation between tags.

InputTagsControl#

InputTagsControl accepts a render-prop child invoked once with { controlProps, add, remove, removeLast, removeAll, value, inputValue, focused }. Spread controlProps onto a text-entry element (plain <input>, <AutoComplete.Input>, etc.). Call add(tag) or add([tag1, tag2]) to commit one or more tags programmatically. When you need the root DOM node (for popup anchors, scroll-into-view, etc.), attach a callback ref via ref={setRootEl} on <InputTags.Root> and use the tracked state.

Accessibility#

Screen Reader#

The root container uses role="listbox" with aria-orientation="horizontal". Each tag (via itemProps) has role="option" with aria-selected, aria-setsize, and aria-posinset. The text-entry element's ARIA depends on what the consumer renders: a plain <input> is just a text field; an <AutoComplete.Input> adds combobox + aria-haspopup / aria-expanded / aria-controls semantics automatically.

Keyboard Support#

KeyFunction
tabMoves focus to the input element.
enterAdds a new tag with the current input value.
backspaceRemoves the last tag when input is empty.
left arrowMoves focus to the previous tag when input is empty.
right arrowMoves focus to the next tag when focused on a tag.

Tag Keyboard Support#

KeyFunction
backspaceRemoves the focused tag.
deleteRemoves the focused tag.