- Alert
- Avatar
- Badge
- Breadcrumb
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Checkbox Group
- ComboBox
- Command
- Data Table
- Date Field
- Date Picker
- Date Range Picker
- Dialog
- Disclosure
- Disclosure Group
- Drawer
- Empty
- Field
- File Trigger
- Form
- Grid List
- Hover Card
- Input
- Input Group
- Input OTP
- Item
- Kbd
- Label
- ListBox
- Menu
- Number Field
- Pagination
- Popover
- Progress Bar
- Radio Group
- Range Calendar
- Resizable
- Search Field
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Tag Group
- Text Field
- Textarea
- Time Field
- Toast
- Toggle Button
- Toggle Button Group
- Tooltip
- Tree
- Typography
A tag group is a focusable list of labels, categories, keywords, filters, or other items, with support for keyboard navigation, selection, and removal.
import { Tag, TagGroup } from "@/components/ui/tag-group"
export function TagGroupDemo() {
return (
<TagGroup
label="Categories"
description="Select your categories"
selectionMode="single"
>
<Tag id="news">News</Tag>
<Tag id="travel">Travel</Tag>
<Tag id="gaming">Gaming</Tag>
<Tag id="shopping">Shopping</Tag>
</TagGroup>
)
}
Installation
pnpmnpmyarnbunpnpm dlx shadcn@latest add tag-group
Usage
import { Tag, TagGroup } from "@/components/ui/tag-group"<TagGroup label="Categories">
<Tag id="news">News</Tag>
<Tag id="travel">Travel</Tag>
<Tag id="gaming">Gaming</Tag>
<Tag id="shopping">Shopping</Tag>
</TagGroup>Features
A tag group displays a collection of tags with rich user interactions. Tags can be static labels, or they can support removal and selection based on your use case.
- Keyboard navigation – Navigate tags using arrow keys, along with page up/down, home/end, and more.
- Removable – Tags can be removed from the group by clicking a remove button or pressing the backspace key.
- Item selection – Support for single or multiple selection with keyboard and mouse interactions.
- Accessible – Follows the ARIA grid pattern, with selection announcements via ARIA live region.
- Styleable – Hover, focus, selection, and disabled states are provided for styling.
Examples
Default
import { Tag, TagGroup } from "@/components/ui/tag-group"
export function TagGroupDemo() {
return (
<TagGroup
label="Categories"
description="Select your categories"
selectionMode="single"
>
<Tag id="news">News</Tag>
<Tag id="travel">Travel</Tag>
<Tag id="gaming">Gaming</Tag>
<Tag id="shopping">Shopping</Tag>
</TagGroup>
)
}
<TagGroup
label="Categories"
description="Select your categories"
selectionMode="single"
>
<Tag id="news">News</Tag>
<Tag id="travel">Travel</Tag>
<Tag id="gaming">Gaming</Tag>
<Tag id="shopping">Shopping</Tag>
</TagGroup>Variants
import { Tag, TagGroup } from "@/components/ui/tag-group"
export function TagGroupVariantsDemo() {
return (
<div className="flex flex-col gap-6">
<TagGroup label="Default" description="Default variant tags">
<Tag id="react">React</Tag>
<Tag id="vue">Vue</Tag>
<Tag id="angular">Angular</Tag>
</TagGroup>
<TagGroup label="Primary" description="Primary variant tags">
<Tag id="react" variant="primary">
React
</Tag>
<Tag id="vue" variant="primary">
Vue
</Tag>
<Tag id="angular" variant="primary">
Angular
</Tag>
</TagGroup>
<TagGroup label="Secondary" description="Secondary variant tags">
<Tag id="react" variant="secondary">
React
</Tag>
<Tag id="vue" variant="secondary">
Vue
</Tag>
<Tag id="angular" variant="secondary">
Angular
</Tag>
</TagGroup>
<TagGroup label="Destructive" description="Destructive variant tags">
<Tag id="bug" variant="destructive">
Bug
</Tag>
<Tag id="error" variant="destructive">
Error
</Tag>
<Tag id="critical" variant="destructive">
Critical
</Tag>
</TagGroup>
<TagGroup label="Outline" description="Outline variant tags">
<Tag id="react" variant="outline">
React
</Tag>
<Tag id="vue" variant="outline">
Vue
</Tag>
<Tag id="angular" variant="outline">
Angular
</Tag>
</TagGroup>
</div>
)
}
<TagGroup label="Primary" description="Primary variant tags">
<Tag id="react" variant="primary">React</Tag>
<Tag id="vue" variant="primary">Vue</Tag>
<Tag id="angular" variant="primary">Angular</Tag>
</TagGroup>
<TagGroup label="Secondary" description="Secondary variant tags">
<Tag id="react" variant="secondary">React</Tag>
<Tag id="vue" variant="secondary">Vue</Tag>
<Tag id="angular" variant="secondary">Angular</Tag>
</TagGroup>
<TagGroup label="Destructive" description="Destructive variant tags">
<Tag id="bug" variant="destructive">Bug</Tag>
<Tag id="error" variant="destructive">Error</Tag>
<Tag id="critical" variant="destructive">Critical</Tag>
</TagGroup>
<TagGroup label="Outline" description="Outline variant tags">
<Tag id="react" variant="outline">React</Tag>
<Tag id="vue" variant="outline">Vue</Tag>
<Tag id="angular" variant="outline">Angular</Tag>
</TagGroup>Available variants: default, primary, secondary, destructive, outline.
Removable Tags
"use client"
import { useState } from "react"
import { Tag, TagGroup } from "@/components/ui/tag-group"
export function TagGroupRemovableDemo() {
const [tags, setTags] = useState([
{ id: 1, name: "React" },
{ id: 2, name: "TypeScript" },
{ id: 3, name: "Tailwind CSS" },
{ id: 4, name: "Next.js" },
])
return (
<TagGroup<{ id: number; name: string }>
label="Tech Stack"
description="Select your tech stack"
items={tags}
onRemove={(keys) => setTags(tags.filter((tag) => !keys.has(tag.id)))}
>
{(item) => <Tag id={item.id}>{item.name}</Tag>}
</TagGroup>
)
}
"use client"
import { useState } from "react"
import { Tag, TagGroup } from "@/components/ui/tag-group"
export default function Example() {
const [tags, setTags] = useState([
{ id: 1, name: "React" },
{ id: 2, name: "TypeScript" },
{ id: 3, name: "Tailwind CSS" },
{ id: 4, name: "Next.js" },
])
return (
<TagGroup
label="Tech Stack"
description="Click × or press backspace to remove"
onRemove={(keys) =>
setTags(tags.filter((tag) => !keys.has(tag.id)))
}
items={tags}
>
{(item) => <Tag id={item.id}>{item.name}</Tag>}
</TagGroup>
)
}Use the onRemove prop to handle tag removal. The remove button appears automatically when this prop is provided. Users can click the × button or press backspace to remove tags.
Selection
"use client"
import { useState } from "react"
import { Tag, TagGroup } from "@/components/ui/tag-group"
export function TagGroupSelectionDemo() {
const [selected, setSelected] = useState<Set<string>>(
new Set(["sports", "music"])
)
return (
<TagGroup
selectionMode="multiple"
selectedKeys={selected}
onSelectionChange={(keys) => setSelected(keys as Set<string>)}
label="Interests"
description="Select your interests"
>
<Tag id="sports">Sports</Tag>
<Tag id="music">Music</Tag>
<Tag id="travel">Travel</Tag>
<Tag id="gaming">Gaming</Tag>
<Tag id="technology">Technology</Tag>
</TagGroup>
)
}
"use client"
import { useState } from "react"
import { Tag, TagGroup } from "@/components/ui/tag-group"
export default function Example() {
const [selected, setSelected] = useState<Set<string>>(
new Set(["sports", "music"])
)
return (
<TagGroup
selectionMode="multiple"
selectedKeys={selected}
onSelectionChange={(keys) => setSelected(keys as Set<string>)}
label="Interests"
description="Select your interests"
>
<Tag id="sports">Sports</Tag>
<Tag id="music">Music</Tag>
<Tag id="travel">Travel</Tag>
<Tag id="gaming">Gaming</Tag>
<Tag id="technology">Technology</Tag>
</TagGroup>
)
}Set selectionMode to "multiple" to enable multiple selection, or "single" for single selection. Use the selectedKeys and onSelectionChange props to manage the selection state.
Links
import Link from "next/link"
import { Tag, TagGroup } from "@/components/ui/tag-group"
export function TagGroupLinksDemo() {
return (
<TagGroup label="Quick Links" description="Select your quick links">
<Tag id="docs">
<Link href="/docs">Documentation</Link>
</Tag>
<Tag id="components">
<Link href="/components">Components</Link>
</Tag>
<Tag id="examples">
<Link href="/examples">Examples</Link>
</Tag>
<Tag id="blocks">
<Link href="/blocks">Blocks</Link>
</Tag>
</TagGroup>
)
}
import Link from "next/link"
import { Tag, TagGroup } from "@/components/ui/tag-group"
<TagGroup label="Quick Links" description="Navigate to different pages">
<Tag id="docs" href="/docs">
<Link href="/docs">Documentation</Link>
</Tag>
<Tag id="components" href="/docs/components">
<Link href="/docs/components">Components</Link>
</Tag>
<Tag id="examples" href="/examples">
<Link href="/examples">Examples</Link>
</Tag>
<Tag id="blocks" href="/blocks">
<Link href="/blocks">Blocks</Link>
</Tag>
</TagGroup>Tags can be used as navigation links by providing an href prop and wrapping the content with a Next.js Link component.
Disabled Tags
import { Tag, TagGroup } from "@/components/ui/tag-group"
export function TagGroupDisabledDemo() {
return (
<TagGroup label="Categories" description="Select your categories">
<Tag id="active">Active</Tag>
<Tag id="disabled" isDisabled>
Disabled
</Tag>
</TagGroup>
)
}
<TagGroup label="Categories" description="Select your categories">
<Tag id="active1">Active</Tag>
<Tag id="disabled1" isDisabled>Disabled</Tag>
<Tag id="active2">Active</Tag>
<Tag id="disabled2" isDisabled>Disabled</Tag>
</TagGroup>Use the isDisabled prop on individual tags to disable them. Disabled tags cannot be selected, removed, or interacted with.
Empty State
"use client"
import { TagGroup } from "@/components/ui/tag-group"
export function TagGroupEmptyDemo() {
return (
<TagGroup
label="Tags"
description="Select your tags"
renderEmptyState={() => <div>No tags available</div>}
></TagGroup>
)
}
<TagGroup
label="Tags"
description="Available tags"
renderEmptyState={() => (
<div className="flex min-h-[100px] items-center justify-center rounded-md border border-dashed">
<p className="text-sm text-muted-foreground">No tags available</p>
</div>
)}
>
{/* Empty - will show renderEmptyState */}
</TagGroup>Use the renderEmptyState prop to show a custom empty state when there are no tags.
API Reference
TagGroup
The TagGroup component is the container for a collection of tags.
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | - | Label text for the tag group. |
description | string | - | Description text displayed below the label. |
errorMessage | string | - | Error message to display. |
selectionMode | "none" | "single" | "multiple" | "none" | Whether tags can be selected and what selection mode to use. |
selectedKeys | Iterable<Key> | - | The currently selected keys (controlled). |
onSelectionChange | (keys: Selection) => void | - | Handler called when the selection changes. |
disabledKeys | Iterable<Key> | - | Keys of tags that are disabled. |
onRemove | (keys: Set<Key>) => void | - | Handler called when tags are removed. Enables remove buttons. |
items | Iterable<T> | - | Item objects for dynamic collections. |
renderEmptyState | () => React.ReactNode | - | Renders when the list is empty. |
Tag
Individual tag items within a tag group.
| Prop | Type | Default | Description |
|---|---|---|---|
id | Key | - | A unique identifier for the tag (required for selection/removal). |
variant | "default" | "primary" | "secondary" | "destructive" | "outline" | "default" | The visual style variant of the tag. |
textValue | string | - | A string representation for accessibility and typeahead. |
href | string | - | URL to navigate to (makes the tag a link). |
isDisabled | boolean | false | Whether the tag is disabled. |
Apart from the props above, the components support all props from the react-aria-components library. Check the React Aria documentation for more details.
Accessibility
Tag groups follow the ARIA grid pattern, which provides keyboard navigation, selection announcements, and focus management.
- Keyboard Navigation – Arrow keys navigate between tags. Home/End move to first/last tag.
- Removal – Press backspace when focused on a tag to remove it (if
onRemoveis provided). - Selection – Space or Enter keys select tags when selection is enabled.
- Screen Readers – Selection state and removal actions are announced via ARIA live regions.
Always provide a label prop or use aria-label to identify the tag group:
<TagGroup label="Categories">
<Tag id="news">News</Tag>
<Tag id="travel">Travel</Tag>
</TagGroup>Related
- Badge - For static status indicators
- Checkbox Group - For selecting multiple options
- Button - For clickable actions