Badge
Data DisplayA compact status label with solid, soft, outline, and accent variants. Drops an icon in cleanly.
bySaumya
SolidSoftOutline Shipped
components/ui/badge.tsx
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const badgeVariants = cva(
"inline-flex items-center gap-1 rounded-full border px-2.5 py-0.5 text-xs font-medium transition-colors [&_svg]:size-3",
{
variants: {
variant: {
solid: "border-transparent bg-accent text-accent-fg",
soft: "border-transparent bg-surface-2 text-foreground",
outline: "border-border text-foreground",
accent:
"border-accent/30 bg-accent/10 text-accent",
},
},
defaultVariants: { variant: "soft" },
},
);
export type BadgeProps = React.ComponentProps<"span"> &
VariantProps<typeof badgeVariants>;
export function Badge({ className, variant, ...props }: BadgeProps) {
return (
<span
data-slot="badge"
className={cn(badgeVariants({ variant, className }))}
{...props}
/>
);
}
export { badgeVariants };Overview
A compact label for statuses, categories, and counts. Four variants cover the common emphasis levels, and an icon slots in cleanly to the left of the text.
When to use
Reach for solid or accent to call attention (a "New" or "Pro" tag), and soft / outline for quiet metadata like tags or categories. Keep the text to one or two words.
Composition
The badge forwards all native span attributes, so you can attach a title,
role, or data attributes as needed. Drop any icon as the first child:
<Badge variant="accent"><Check /> Shipped</Badge>
Installation
Terminal
npx shadcn@latest add https://ui.saumyarex.xyz/r/badge.json1. Install dependencies
Terminal
npm install class-variance-authority clsx tailwind-merge2. Copy the source into your project
components/ui/badge.tsx
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const badgeVariants = cva(
"inline-flex items-center gap-1 rounded-full border px-2.5 py-0.5 text-xs font-medium transition-colors [&_svg]:size-3",
{
variants: {
variant: {
solid: "border-transparent bg-accent text-accent-fg",
soft: "border-transparent bg-surface-2 text-foreground",
outline: "border-border text-foreground",
accent:
"border-accent/30 bg-accent/10 text-accent",
},
},
defaultVariants: { variant: "soft" },
},
);
export type BadgeProps = React.ComponentProps<"span"> &
VariantProps<typeof badgeVariants>;
export function Badge({ className, variant, ...props }: BadgeProps) {
return (
<span
data-slot="badge"
className={cn(badgeVariants({ variant, className }))}
{...props}
/>
);
}
export { badgeVariants };lib/utils.ts
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
/** Merge conditional class names and resolve Tailwind conflicts. */
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "solid" | "soft" | "outline" | "accent" | "soft" | Visual style of the badge. |
...props | React.ComponentProps<"span"> | — | All native span attributes are forwarded. |
Dependencies
class-variance-authorityclsxtailwind-merge