Tag
Data Display
Interactive
Removable labels for categorization, filtering, and selections. Interactive alternative to static badges.
Preview
Interactive tag examples
ReactTypeScriptNext.jsTailwind
Variants
All available tag styles
DefaultPrimarySecondarySuccessWarningErrorInfoVioletOutline
Sizes
Available tag sizes
SmallMediumLarge
With Icons
Tags with leading icons
VerifiedFeaturedPremiumTrending
Removable Tags
Tags that can be removed
DefaultPrimarySuccessError
Click the X button to trigger the onRemove callback.
Clickable Tags
Tags as toggleable filters
DesignDevelopmentMarketingSales
Selected: Design
Disabled State
Disabled tags for read-only display
DisabledNot RemovableNot Clickable
With Truncation
Tags with max width for long labels
Very Long Tag Label That Gets TruncatedAnother Long Label Here
Use Cases
Common tag patterns
Email Labels
UrgentWorkPersonalFollow-up
Skills/Technologies
javascriptreacttypescriptnode
Status Indicators
CompletedIn ReviewBlockedDraft
Props
Tag component API reference
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' | 'violet' | 'outline' | 'default' | Visual style variant for the tag |
size | 'sm' | 'md' | 'lg' | 'md' | Size of the tag |
icon | React.ReactNode | — | Optional icon to display before the label |
removable | boolean | false | Whether the tag shows a remove button |
onRemove | () => void | — | Callback when the remove button is clicked |
clickable | boolean | false | Whether the tag is clickable |
onClick | () => void | — | Callback when the tag is clicked (requires clickable=true) |
disabled | boolean | false | Whether the tag is disabled |
maxWidth | string | number | — | Max width for truncation |
className | string | — | Additional CSS classes for custom styling |
Usage
Import and implementation example
import { Tag } from '@/components/ui/tag'
export default function Example() {
const [tags, setTags] = useState(['React', 'TypeScript', 'Next.js'])
const removeTag = (tagToRemove: string) => {
setTags(tags.filter(tag => tag !== tagToRemove))
}
return (
<div className="flex flex-wrap gap-2">
{tags.map(tag => (
<Tag
key={tag}
variant="primary"
removable
onRemove={() => removeTag(tag)}
>
{tag}
</Tag>
))}
</div>
)
}Features
Built-in functionality
- 9 variants: Default, primary, secondary, success, warning, error, info, violet, and outline styles
- 3 sizes: Small, medium, and large sizes
- Removable: Optional X button with onRemove callback
- Clickable: Can function as toggleable filter buttons
- Icon support: Optional leading icon
- Truncation: Max width option for long labels
- Disabled state: Visual and interaction disabled state
- Dark mode: Full dark mode support with proper color contrast
Accessibility
ARIA support and keyboard navigation
ARIA Attributes
role="button" (when clickable)aria-disabled (when disabled)aria-label (on remove button)Keyboard Navigation
| Key | Action |
|---|---|
| Tab | Move focus to tag (when clickable) or remove button |
| Enter / Space | Activate tag click or remove action |
Notes
- Clickable tags are keyboard accessible with Enter/Space activation
- Remove buttons have descriptive aria-labels including tag content
- Disabled state prevents both mouse and keyboard interaction
- Focus indicators are visible on interactive elements