import { TagBox, type TagType } from "@/components/tag-box"
Tag Box
A versatile component for managing and displaying tags with rich customization options.
Playground
Customize the Tag Box properties to see different variations.
This example demonstrates the TagBox with Radix UI Popover for positioning. The dropdown will be correctly positioned and not clipped by parent containers.
Customize
Installation
pnpm dlx shadcn@latest add https://shadcn-ui-variants.vercel.app/r/tag-box.json
Overview
The TagBox
component offers a robust and user-friendly solution for managing tags within your application. It empowers users to effortlessly add, select, remove, and edit tags, complete with suggestions, customizable appearances, and flexible state management options (controlled and uncontrolled). It's designed to integrate seamlessly with your UI, leveraging components like Badges, Popovers, and Modals for a rich interactive experience.
Features
- Tag Input: Add tags by typing or selecting from a dynamic list of suggestions.
- Tag Creation: Dynamically create new tags if they don't exist in the predefined list.
- Tag Removal: Easily remove selected tags with a single click on the 'x' icon.
- Tag Management Interface: A built-in modal allows users to edit tag names and colors (if enabled) for all known tags.
- Color Customization: Assign distinct colors to tags for better visual organization. This feature can be globally toggled using the
withColor
prop. - Controlled and Uncontrolled Modes: Flexible state management. Use it as a controlled component by providing
value
andonChange
props, or as an uncontrolled component withdefaultValue
. - Max Tags Limit: Set a maximum number of selectable tags, with visual feedback when the limit is reached.
- Customizable Placeholders: Define custom placeholder text for the input field.
- Styling: Leverages
Badge
component for tag display, allowing easy styling via inherited props or custom class names (className
,tagClassName
). - Accessibility: Built with Radix UI primitives, focusing on accessibility and keyboard navigation.
Basic Usage
Import the TagBox
component and, optionally, the TagType
for typing your tag data.
<TagBox userTags={availableUserTags} />
For a minimal setup, you can provide an array of userTags
which are the predefined tags available for selection and management.
Controlled vs. Uncontrolled Mode
TagBox
can operate in two modes:
- Controlled Mode: You manage the state of selected tags. Provide the
value
prop (an array of selectedTagType
objects) and handle updates via theonChange
callback. This gives you full control over the tag selection state.const [selectedTags, setSelectedTags] = React.useState<TagType[]>([]); <TagBox userTags={allMyTags} value={selectedTags} onChange={setSelectedTags} />
- Uncontrolled Mode: The component manages its own selection state internally. You can provide a
defaultValue
prop for the initial set of selected tags. You can still listen to changes using theonChange
callback if needed. This mode is simpler for basic use cases.<TagBox userTags={allMyTags} defaultValue={[{ id: "1", name: "Initial Tag" }]} onChange={(tags) => console.log("Tags changed:", tags)} />
Tag Management Callbacks
The "Manage tags" dialog allows users to modify the global list of available tags. To persist these changes, use the onTagEdit
and onTagRemove
callbacks:
onTagEdit
: Called when a tag's name or color is saved in the management dialog. You should update your master list ofuserTags
(e.g., in your state or database) with the received updated tag object.onTagRemove
: Called when a tag is deleted from the management dialog. You should remove this tag from your master list ofuserTags
.
Properly handling these callbacks ensures that changes made in the "Manage tags" dialog are reflected globally and persist as needed.
Examples
With Maximum Tags Limit & Uncontrolled
Demonstrates limiting the number of selectable tags with a visual indicator, used in an uncontrolled manner with a default value.
Custom Styling & Inner Tags
Customize the appearance of the TagBox and its tags.
Controlled Mode & Form Integration
Illustrates using TagBox as a controlled component within a form, managing its state and potentially integrating with form validation.
Tag Management & Real-time Filtering
An advanced example showing how to handle onTagEdit
and onTagRemove
to manage userTags
, and using selected tags to filter a list of items in real-time. Tag editing and creation are disabled.
Filter Tasks by Tags:
Badge Props Integration
The TagBox
component renders each selected tag using an internal Badge
component. You can directly pass props supported by the Badge
component (such as variant
, size
, shape
, leftElement
, rightElement
) to the TagBox
. These props will be applied to each individual tag badge. For example, to change the shape of all tags:
<TagBox userTags={userTags} shape="square" />
Refer to the Badge
component documentation for a full list of available props and their effects. The tagClassName
prop can also be used for more specific CSS customization of the badges.
Notes and Best Practices
- Unique Tag IDs: While not strictly enforced for basic operation if only names are used, providing unique
id
fields in yourTagType
objects is highly recommended, especially for stable keying, reliable editing, and removal when tag names might not be unique or could change. The component will generate a temporary random ID for newly created tags if an ID is not part of the `existingUserTag` or implicitly handled by your `onTagEdit` logic for new tags. - State Management for
userTags
: TheuserTags
prop provides the initial set of available tags. If you allow tag creation or editing through the "Manage Tags" dialog, you are responsible for updating your sourceuserTags
array using theonTagEdit
andonTagRemove
callbacks to ensure consistency. - Performance: For very large sets of
userTags
or selected tags, consider performance implications. Virtualization for the suggestion list is not built-in but could be a custom enhancement if needed. - Styling Conflicts: Be mindful of CSS specificity if applying extensive custom styles, especially when using
className
andtagClassName
alongside inherited Badge props.
TagBox Props
Prop | Type | Default |
---|---|---|
value | TagType[] | — |
defaultValue | TagType[] | — |
onChange | function | — |
name | string | — |
userTags | TagType[] | — |
onTagEdit | function | — |
onTagRemove | function | — |
maxTags | number | — |
showMaxTags | boolean | false |
placeholder | string | "Type or select tags..." |
placeholderWhenFull | string | "Max tags reached" |
className | string | — |
tagClassName | string | — |
withColor | boolean | true |
openOnFocus | boolean | true |
enableCreate | boolean | true |
enableManage | boolean | true |
tagsPosition | enum | "bottom" |
disabled | boolean | false |