@codav/tag-input
v1.0.2
Published
A customizable React tag input component with comma and Enter parsing
Downloads
62
Readme
@codav/tag-input
A powerful, customizable, TypeScript-first React Tag Input component with keyboard support, comma parsing, RTL/LTR support, duplicate prevention, and flexible styling.
✨ Overview
@codav/tag-input is a lightweight, reusable, and highly customizable React Tag Input component built with TypeScript.
It provides a modern input experience for creating, managing, and removing tags using:
EnterComma (, )Backspace- Optional action button
- Blur-to-add behavior
The component is designed to work naturally with React, Next.js, TypeScript, admin dashboards, CMS platforms, forms, blogs, e-commerce applications, and modern design systems.
🚀 Why @codav/tag-input?
Building a good tag input sounds simple until you need:
- Keyboard interactions
- Duplicate prevention
- Maximum tag limits
- RTL support
- Custom tag rendering
- Custom styling
- Controlled state
- Accessibility
- Next.js compatibility
- Clean TypeScript types
@codav/tag-input provides these capabilities in a single reusable component.
🎯 Features
- ⚡ Lightweight React component
- 🔷 TypeScript-first
- ⚛️ React 18+ compatible
- ▲ Next.js compatible
- ⌨️ Enter-to-add
,comma-to-add- ⌫ Backspace-to-remove
- 🖱️ Optional add button
- 🔄 Add multiple tags at once
- 🚫 Duplicate prevention
- 🔢 Maximum tag limit
- 🧩 Custom tag renderer
- 🎨 Highly customizable styling
- 🌐 RTL / LTR / Auto direction
- ♿ Keyboard-friendly interaction
- 🧱 Controlled component API
- 🪶 Small production build
- 📦 ESM + CommonJS
- 🔌 Easy integration
- 🌙 Tailwind-friendly
- 🛠️ Standard HTML input attributes
📦 Installation
npm install @codav/tag-inputUsing legacy peer dependency resolution:
npm install @codav/tag-input --legacy-peer-deps⚡ Quick Start
"use client";
import { useState } from "react";
import { Tag } from "lucide-react";
import { TagInput } from "@codav/tag-input";
export default function Example() {
const [tags, setTags] = useState<string[]>([]);
return (
<TagInput
label="Tags"
value={tags}
onChange={setTags}
placeholder="Type a tag and press Enter..."
icon={Tag}
/>
);
}🇮🇷 Persian / RTL Example
"use client";
import { useState } from "react";
import { Tag } from "lucide-react";
import { TagInput } from "@codav/tag-input";
export default function PersianTags() {
const [tags, setTags] = useState<string[]>([]);
return (
<TagInput
label="برچسبها"
description="برچسبها را با کاما یا Enter اضافه کنید"
value={tags}
onChange={setTags}
placeholder="مثلاً Laravel، React، Next.js"
icon={Tag}
direction="rtl"
/>
);
}⌨️ Keyboard Interaction
The component is designed around fast keyboard interaction.
| Action | Result |
|---|---|
| Enter | Add current input as a tag |
| , | Parse and add tags |
| Backspace | Remove the last tag when input is empty |
| Blur | Optionally add current input |
Example:
LaravelPress:
EnterResult:
["Laravel"]🏷️ Multiple Tags
You can enter multiple comma-separated values:
Laravel, React, Next.js, TypeScriptThe component converts them into:
[
"Laravel",
"React",
"Next.js",
"TypeScript"
]🎨 Custom Styling
One of the main goals of this package is styling flexibility.
You can customize:
- Wrapper
- Input
- Tags
- Remove buttons
- Action button
- Custom rendered tags
Example:
<TagInput
value={tags}
onChange={setTags}
wrapperClassName="space-y-2"
inputClassName="font-medium"
tagClassName="rounded-full bg-primary/10 text-primary"
tagRemoveClassName="hover:bg-red-500 hover:text-white"
buttonClassName="rounded-full"
/>🧩 Custom Tag Rendering
For complete control over the tag UI, use renderTag.
<TagInput
value={tags}
onChange={setTags}
renderTag={(tag, index, remove) => (
<button
type="button"
onClick={remove}
className="rounded-full bg-black px-3 py-1 text-sm text-white"
>
{tag}
</button>
)}
/>The callback receives:
(
tag: string,
index: number,
remove: () => void
) => ReactNodeThis makes it possible to create completely custom tag designs.
🔢 Maximum Tags
Limit the number of tags:
<TagInput
value={tags}
onChange={setTags}
maxTags={10}
/>Once the limit is reached, additional tags are ignored.
🚫 Duplicate Prevention
Duplicate tags are prevented by default.
<TagInput
value={tags}
onChange={setTags}
/>For example:
React
react
REACTare treated as duplicates.
To allow duplicates:
<TagInput
value={tags}
onChange={setTags}
allowDuplicates
/>🔧 Custom Separator
The default separator is:
,You can customize it:
<TagInput
value={tags}
onChange={setTags}
separator=";"
/>Now:
Laravel;React;Next.jsbecomes:
[
"Laravel",
"React",
"Next.js"
]🖱️ Add on Blur
By default, the component can add the current input when the field loses focus.
<TagInput
value={tags}
onChange={setTags}
addOnBlur
/>Disable it:
<TagInput
value={tags}
onChange={setTags}
addOnBlur={false}
/>🌐 RTL / LTR
RTL:
<TagInput
direction="rtl"
value={tags}
onChange={setTags}
/>LTR:
<TagInput
direction="ltr"
value={tags}
onChange={setTags}
/>Automatic:
<TagInput
direction="auto"
value={tags}
onChange={setTags}
/>🧱 Controlled State
TagInput is a fully controlled component.
const [tags, setTags] = useState<string[]>([]);
<TagInput
value={tags}
onChange={setTags}
/>Your application remains responsible for the actual tag data.
🛑 Disabled State
<TagInput
value={tags}
onChange={setTags}
disabled
/>When disabled:
- Input is disabled
- Tags cannot be removed
- New tags cannot be added
- Action button is disabled
❌ Error State
<TagInput
label="Tags"
value={tags}
onChange={setTags}
error="Please add at least one tag."
/>🏷️ Labels and Descriptions
<TagInput
label="Technologies"
description="Add technologies used in this project."
value={tags}
onChange={setTags}
/>🧑💻 Real-World Example
"use client";
import { useState } from "react";
import { Tag } from "lucide-react";
import { TagInput } from "@codav/tag-input";
export default function ProjectTags() {
const [tags, setTags] = useState<string[]>([]);
return (
<div className="space-y-6">
<TagInput
label="Project Technologies"
description="Add technologies using comma or Enter."
value={tags}
onChange={setTags}
placeholder="Laravel, React, Next.js..."
icon={Tag}
direction="ltr"
maxTags={20}
/>
<pre>
{JSON.stringify(tags, null, 2)}
</pre>
</div>
);
}📚 API
TagInputProps
export type TagInputProps = {
value: string[];
onChange: (
tags: string[]
) => void;
label?: string;
description?: string;
error?: string;
icon?: ComponentType<{
className?: string;
}>;
separator?: string;
addOnBlur?: boolean;
allowDuplicates?: boolean;
maxTags?: number;
direction?:
| "ltr"
| "rtl"
| "auto";
generateButton?: boolean;
generateButtonLabel?: string;
wrapperClassName?: string;
inputClassName?: string;
tagClassName?: string;
tagRemoveClassName?: string;
buttonClassName?: string;
renderTag?: (
tag: string,
index: number,
remove: () => void
) => ReactNode;
};The component also supports standard HTML input attributes.
▲ Next.js Support
@codav/tag-input works with the Next.js App Router.
Because the component uses client-side React state and browser events, import it from a Client Component:
"use client";
import { TagInput } from "@codav/tag-input";🔷 TypeScript
The package is written in TypeScript and is designed for TypeScript projects.
import {
TagInput,
type TagInputProps,
} from "@codav/tag-input";📦 Build Output
The package generates modern ESM and CommonJS builds.
dist/
├── index.mjs
├── index.js
├── index.mjs.map
└── index.js.map🛠️ Development
Clone the repository:
git clone https://github.com/MohammadMahdiAhmadi1382/react-tag-input.gitEnter the project:
cd react-tag-inputInstall dependencies:
npm installRun the production build:
npm run build📁 Project Structure
react-tag-input/
│
├── src/
│ ├── index.ts
│ ├── types.ts
│ └── TagInput.tsx
│
├── dist/
│ ├── index.js
│ ├── index.mjs
│ ├── index.js.map
│ └── index.mjs.map
│
├── package.json
├── tsconfig.json
├── tsup.config.ts
├── README.md
└── LICENSE🧠 Design Principles
Minimal API
The simplest implementation only requires:
<TagInput
value={tags}
onChange={setTags}
/>Application-Owned State
The component does not manage your final tag collection.
Your application owns the data.
Flexible UI
The package does not force a specific design system.
Style hooks allow the component to adapt to existing applications.
Keyboard First
Fast data entry is a core feature.
Enter → Add
Comma → Add
Backspace → RemoveFramework Friendly
Designed for:
- React
- Next.js
- TypeScript
- Admin panels
- CMS
- SaaS dashboards
- E-commerce
- CRM
- Blogs
- Forms
- Search interfaces
💡 Use Cases
@codav/tag-input can be used for:
- Blog tags
- Article keywords
- SEO keywords
- Product tags
- Product attributes
- Search filters
- User interests
- Skills
- Technologies
- Categories
- Project labels
- Course tags
- Student skills
- Content metadata
- Permissions
- Email recipients
- Feature lists
- CMS metadata
🔌 Dependencies
The package uses:
- React
- React DOM
clsxlucide-react
The component does not depend on application-specific UI components.
🌍 Browser Target
The package targets:
ES2020and is intended for modern browsers and JavaScript environments.
📈 Performance
The component is designed to remain lightweight and dependency-conscious.
The production package contains only the generated distribution files required by consumers.
🤝 Contributing
Contributions are welcome.
Before creating a pull request:
npm install
npm run buildPlease ensure the package builds successfully.
For bug reports, include:
- Package version
- React version
- Next.js version if applicable
- Browser
- Operating system
- Reproduction steps
- Expected behavior
- Actual behavior
🐛 Issues & Feature Requests
Found a bug or have an idea?
Open an issue in the GitHub repository:
https://github.com/MohammadMahdiAhmadi1382/react-tag-input/issues
Please provide enough information to reproduce the problem.
📜 License
MIT License
Copyright (c) Mohammad Mahdi Ahmadi / CODAVO
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files, to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software.
The software is provided "as is", without warranty of any kind.
👨💻 Author
Mohammad Mahdi Ahmadi
Full-Stack Developer & Software Engineer
GitHub:
https://github.com/MohammadMahdiAhmadi1382
🏢 CODAVO
Part of the reusable frontend and developer tooling ecosystem developed by CODAVO.
The goal is to build clean, reusable, production-oriented packages that can be integrated into modern web applications with minimal configuration.
🔗 Links
GitHub Repository
https://github.com/MohammadMahdiAhmadi1382/react-tag-input
NPM Package
https://www.npmjs.com/package/@codav/tag-input
Author
https://github.com/MohammadMahdiAhmadi1382
⭐ Support
If this package is useful to you, consider giving the repository a ⭐ on GitHub.
Your feedback, issues, and contributions help improve the project.
Keywords
react reactjs react-component tag-input tags-input input-component typescript nextjs next.js npm ui-component form-component form-input multi-input multi-value-input chips-input token-input keyword-input react-tags tag-editor rtl ltr tailwindcss frontend web-development codav
