Badge
Pill-shaped status badges and labels with solid and outline styles, color variants, optional dot indicator, and removable support.
Preview
Solid variants
import { Badge } from '@/registry/ui-kit/tailwind-badge/react'
function Example() {
return (
<div className="flex flex-wrap gap-2">
<Badge>Default</Badge>
<Badge variant="primary">Primary</Badge>
<Badge variant="success">Success</Badge>
<Badge variant="danger">Danger</Badge>
<Badge variant="warning">Warning</Badge>
<Badge variant="info">Info</Badge>
</div>
)
}Outline variants
import { Badge } from '@/registry/ui-kit/tailwind-badge/react'
function Example() {
return (
<div className="flex flex-wrap gap-2">
<Badge outline>Default</Badge>
<Badge variant="primary" outline>Primary</Badge>
<Badge variant="success" outline>Success</Badge>
<Badge variant="danger" outline>Danger</Badge>
<Badge variant="warning" outline>Warning</Badge>
<Badge variant="info" outline>Info</Badge>
</div>
)
}With dot
import { Badge } from '@/registry/ui-kit/tailwind-badge/react'
function Example() {
return (
<div className="flex flex-wrap gap-2">
<Badge variant="success" dot>Active</Badge>
<Badge variant="danger" dot>Offline</Badge>
</div>
)
}Removable
import { Badge } from '@/registry/ui-kit/tailwind-badge/react'
function Example() {
return (
<Badge variant="primary" removable onRemove={() => console.log('removed')}>
React
</Badge>
)
}Component API
| Prop | Default | Description |
|---|---|---|
variant | "default" | Color variant of the badge. |
outline | false | Render as an outline badge with a border and tinted text. |
size | "md" | Size of the badge. |
dot | false | Show a colored dot indicator before the text. |
removable | false | Show a remove (X) button after the text. |
onRemove | — | Callback fired when the remove button is clicked. |
className | "" | Additional CSS classes. |
Source Code
"use client";
import { forwardRef } from "react";
/* ── Variant styles ── */
const solidStyles = {
default: "bg-zinc-100 text-zinc-700 dark:bg-zinc-500/10 dark:text-zinc-400",
primary: "bg-indigo-50 text-indigo-700 dark:bg-indigo-500/10 dark:text-indigo-400",
success: "bg-emerald-50 text-emerald-700 dark:bg-emerald-500/10 dark:text-emerald-400",
danger: "bg-rose-50 text-rose-700 dark:bg-rose-500/10 dark:text-rose-400",
warning: "bg-amber-50 text-amber-700 dark:bg-amber-500/10 dark:text-amber-400",
info: "bg-sky-50 text-sky-700 dark:bg-sky-500/10 dark:text-sky-400",
};
const outlineStyles = {
default: "border border-zinc-200 text-zinc-700 dark:border-zinc-500/30 dark:text-zinc-400",
primary: "border border-indigo-200 text-indigo-700 dark:border-indigo-500/30 dark:text-indigo-400",
success: "border border-emerald-200 text-emerald-700 dark:border-emerald-500/30 dark:text-emerald-400",
danger: "border border-rose-200 text-rose-700 dark:border-rose-500/30 dark:text-rose-400",
warning: "border border-amber-200 text-amber-700 dark:border-amber-500/30 dark:text-amber-400",
info: "border border-sky-200 text-sky-700 dark:border-sky-500/30 dark:text-sky-400",
};
const dotColors = {
default: "bg-zinc-500",
primary: "bg-indigo-500",
success: "bg-emerald-500",
danger: "bg-rose-500",
warning: "bg-amber-500",
info: "bg-sky-500",
};
const sizeStyles = {
sm: "px-1.5 py-0.5 text-xs",
md: "px-2 py-0.5 text-xs",
lg: "px-2.5 py-1 text-sm",
};
const dotSizes = {
sm: "h-1 w-1",
md: "h-1.5 w-1.5",
lg: "h-2 w-2",
};
type BadgeVariant = keyof typeof solidStyles;
type BadgeSize = keyof typeof sizeStyles;
/* ── Badge ── */
interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
variant?: BadgeVariant;
outline?: boolean;
size?: BadgeSize;
dot?: boolean;
removable?: boolean;
onRemove?: () => void;
className?: string;
children: React.ReactNode;
}
const Badge = forwardRef<HTMLSpanElement, BadgeProps>(
({ variant = "default", outline = false, size = "md", dot = false, removable = false, onRemove, className = "", children, ...props }, ref) => {
const variantClass = outline ? outlineStyles[variant] : solidStyles[variant];
const sizeClass = sizeStyles[size];
return (
<span
ref={ref}
className={`inline-flex items-center gap-1.5 rounded-full font-medium ${variantClass} ${sizeClass} ${className}`}
{...props}
>
{dot && (
<span className={`shrink-0 rounded-full ${dotColors[variant]} ${dotSizes[size]}`} />
)}
{children}
{removable && (
<button
type="button"
onClick={onRemove}
className="inline-flex shrink-0 items-center justify-center rounded-full p-0.5 opacity-60 transition-opacity hover:opacity-100"
aria-label="Remove"
>
<svg className="h-3 w-3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M18 6 6 18" />
<path d="m6 6 12 12" />
</svg>
</button>
)}
</span>
);
}
);
Badge.displayName = "Badge";
export { Badge };
export type { BadgeVariant, BadgeSize };
export default Badge;