shadcn/ui Badge is a small, flexible component for labeling and categorizing content. These 4 examples cover all common badge patterns.
Installation
npx shadcn@latest add badge
Usage
import { Badge } from "@/components/ui/badge"
<Badge>Default</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="destructive">Error</Badge>
<Badge variant="outline">Outline</Badge>
1. shadcn/ui Badge Variants
All shadcn/ui badge variants — default, secondary, destructive and outline.
tsx
import { Badge } from "@/components/ui/badge"
export default function BadgeVariants() {
return (
<div className="space-y-4">
{/* shadcn variants */}
<div>
<p className="text-sm text-muted-foreground mb-2">shadcn/ui variants</p>
<div className="flex flex-wrap gap-2">
<Badge>Default</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="destructive">Destructive</Badge>
<Badge variant="outline">Outline</Badge>
</div>
</div>
{/* Custom color badges */}
<div>
<p className="text-sm text-muted-foreground mb-2">Custom Tailwind colors</p>
<div className="flex flex-wrap gap-2">
<span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-semibold text-white" style={{ background: "#fd4766" }}>Brand</span>
<span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-semibold bg-green-100 text-green-700">Success</span>
<span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-semibold bg-yellow-100 text-yellow-700">Warning</span>
<span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-semibold bg-blue-100 text-blue-700">Info</span>
<span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-semibold bg-gray-100 text-gray-600">Neutral</span>
<span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-semibold bg-purple-100 text-purple-700">Premium</span>
</div>
</div>
{/* Pill vs rounded */}
<div>
<p className="text-sm text-muted-foreground mb-2">Shape variants</p>
<div className="flex flex-wrap gap-2 items-center">
<span className="inline-flex px-2.5 py-0.5 rounded text-xs font-semibold bg-gray-100 text-gray-700">Square-ish</span>
<span className="inline-flex px-2.5 py-0.5 rounded-full text-xs font-semibold bg-gray-100 text-gray-700">Pill</span>
<span className="inline-flex px-1.5 py-0.5 rounded text-xs font-bold text-white" style={{ background: "#fd4766", minWidth: "20px", justifyContent: "center" }}>3</span>
</div>
</div>
</div>
)
}2. React Status Badges
Status indicator badges with colored dots — common in user lists, order tables and dashboards.
tsx
import { Badge } from "@/components/ui/badge"
type Status = "active" | "inactive" | "pending" | "draft" | "archived"
const statusConfig: Record<Status, { label: string; dot: string; bg: string; text: string }> = {
active: { label: "Active", dot: "#10b981", bg: "bg-green-50", text: "text-green-700" },
inactive: { label: "Inactive", dot: "#6b7280", bg: "bg-gray-50", text: "text-gray-600" },
pending: { label: "Pending", dot: "#f59e0b", bg: "bg-yellow-50", text: "text-yellow-700"},
draft: { label: "Draft", dot: "#4f6ef7", bg: "bg-blue-50", text: "text-blue-700" },
archived: { label: "Archived", dot: "#ef4444", bg: "bg-red-50", text: "text-red-700" },
}
function StatusBadge({ status }: { status: Status }) {
const config = statusConfig[status]
return (
<span className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-semibold ${config.bg} ${config.text}`}>
<span className="w-1.5 h-1.5 rounded-full" style={{ background: config.dot }} />
{config.label}
</span>
)
}
const templates = [
{ name: "Marvel Dashboard", framework: "Angular 21", status: "active" as Status },
{ name: "PORTO Template", framework: "Bootstrap 5", status: "active" as Status },
{ name: "Proctu Medical", framework: "React 19", status: "pending" as Status },
{ name: "Kiosk Dashboard", framework: "Next.js 15", status: "draft" as Status },
{ name: "CANVA UI Kit", framework: "Bootstrap 5", status: "archived" as Status },
]
export default function StatusBadges() {
return (
<div className="space-y-4">
{/* Status legend */}
<div className="flex flex-wrap gap-2">
{(Object.keys(statusConfig) as Status[]).map((s) => (
<StatusBadge key={s} status={s} />
))}
</div>
{/* In a table */}
<div className="rounded-lg border overflow-hidden">
<table className="w-full text-sm">
<thead className="bg-gray-50">
<tr>
<th className="text-left px-4 py-2.5 font-semibold text-gray-600">Template</th>
<th className="text-left px-4 py-2.5 font-semibold text-gray-600">Framework</th>
<th className="text-left px-4 py-2.5 font-semibold text-gray-600">Status</th>
</tr>
</thead>
<tbody className="divide-y">
{templates.map((t) => (
<tr key={t.name} className="hover:bg-gray-50">
<td className="px-4 py-3 font-medium">{t.name}</td>
<td className="px-4 py-3 text-gray-500">{t.framework}</td>
<td className="px-4 py-3"><StatusBadge status={t.status} /></td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)
}3. React Notification Count Badges
Notification badges overlaid on buttons and icons using absolute positioning.
tsx
import { Button } from "@/components/ui/button"
import { Bell, MessageSquare, ShoppingCart, Mail } from "lucide-react"
export default function NotificationBadges() {
return (
<div className="space-y-6">
{/* Icon buttons with notification counts */}
<div>
<p className="text-sm text-muted-foreground mb-3">Icon notification badges</p>
<div className="flex items-center gap-4">
<button className="relative p-2 text-gray-600 hover:bg-gray-100 rounded-lg">
<Bell size={22} />
<span className="absolute -top-1 -right-1 w-5 h-5 rounded-full text-white text-xs font-bold flex items-center justify-center" style={{ background: "#fd4766", fontSize: "0.6rem" }}>4</span>
</button>
<button className="relative p-2 text-gray-600 hover:bg-gray-100 rounded-lg">
<MessageSquare size={22} />
<span className="absolute -top-1 -right-1 w-5 h-5 rounded-full text-white text-xs font-bold flex items-center justify-center" style={{ background: "#fd4766", fontSize: "0.6rem" }}>12</span>
</button>
<button className="relative p-2 text-gray-600 hover:bg-gray-100 rounded-lg">
<ShoppingCart size={22} />
<span className="absolute -top-1 -right-1 w-5 h-5 rounded-full text-white text-xs font-bold flex items-center justify-center" style={{ background: "#10b981", fontSize: "0.6rem" }}>3</span>
</button>
<button className="relative p-2 text-gray-600 hover:bg-gray-100 rounded-lg">
<Mail size={22} />
<span className="absolute -top-1 -right-1 w-4 h-4 rounded-full" style={{ background: "#fd4766" }} />
</button>
</div>
</div>
{/* Button with badge */}
<div>
<p className="text-sm text-muted-foreground mb-3">Buttons with badges</p>
<div className="flex flex-wrap gap-3">
<Button variant="outline" className="relative gap-2">
<Bell size={15} />
Notifications
<span className="ml-1 px-1.5 py-0.5 rounded-full text-white text-xs font-bold" style={{ background: "#fd4766", fontSize: "0.65rem" }}>4</span>
</Button>
<Button variant="outline" className="relative gap-2">
<MessageSquare size={15} />
Messages
<span className="ml-1 px-1.5 py-0.5 rounded-full text-white text-xs font-bold" style={{ background: "#4f6ef7", fontSize: "0.65rem" }}>99+</span>
</Button>
</div>
</div>
{/* Nav item with badge */}
<div>
<p className="text-sm text-muted-foreground mb-3">Sidebar nav item with badge</p>
<div className="w-48 bg-white border rounded-lg p-2">
{[
{ label: "Dashboard", count: null },
{ label: "Orders", count: 12 },
{ label: "Messages", count: 4 },
{ label: "Reports", count: null },
].map((item) => (
<div key={item.label} className="flex items-center justify-between px-3 py-2 rounded-md hover:bg-gray-50 text-sm cursor-pointer">
<span className="text-gray-700">{item.label}</span>
{item.count && (
<span className="text-white text-xs px-1.5 py-0.5 rounded-full" style={{ background: "#fd4766", fontSize: "0.62rem" }}>
{item.count}
</span>
)}
</div>
))}
</div>
</div>
</div>
)
}Frequently Asked Questions
Run npx shadcn@latest add badge. This creates components/ui/badge.tsx in your project. Import with: import { Badge } from '@/components/ui/badge'.
Use className to override: <Badge className='bg-green-100 text-green-700 hover:bg-green-200'>. Or pass inline style for brand colors: <Badge style={{ background: '#fd4766', color: '#fff' }}>. For reusable custom variants edit badge.tsx directly.
Wrap the button in a relative div, then add the badge with position absolute: <div className='relative'><button>...</button><span className='absolute -top-1 -right-1 w-5 h-5 rounded-full bg-red-500 text-white text-xs flex items-center justify-center'>4</span></div>.
Need a Full React + Next.js Dashboard Template?
Get a complete React + Next.js dashboard with 50+ components — built by the same team behind BootstrapPlanet.
Browse Templates →Use code FIRST30 for 30% off.