UI/UI
Badge
A versatile badge component for displaying status, labels, or categories.
DefaultSecondaryOutlineGhostDestructive
<div className="flex gap-4 flex-wrap">
<Badge>Default</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="outline">Outline</Badge>
<Badge variant="ghost">Ghost</Badge>
<Badge variant="destructive">Destructive</Badge>
</div>
Installation
Install following dependencies:
npm install class-variance-authority lucide-react
pnpm add class-variance-authority lucide-react
yarn add class-variance-authority lucide-react
bun add class-variance-authority lucide-react
Copy and paste the following code into your project.
"use client";
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
import { type LucideIcon } from "lucide-react";
const badgeVariants = cva(
"inline-flex items-center justify-center rounded-md border text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
default:
"border-transparent bg-[hsl(var(--hu-primary))] text-[hsl(var(--hu-primary-foreground))] hover:bg-[hsl(var(--hu-primary))]/80 focus-visible:ring-[hsl(var(--hu-ring))]",
secondary:
"border-transparent bg-[hsl(var(--hu-secondary))] text-[hsl(var(--hu-secondary-foreground))] hover:bg-[hsl(var(--hu-secondary))]/80 focus-visible:ring-[hsl(var(--hu-ring))]",
destructive:
"border-transparent bg-[hsl(var(--hu-destructive))] text-[hsl(var(--hu-destructive-foreground))] hover:bg-[hsl(var(--hu-destructive))]/80 focus-visible:ring-[hsl(var(--hu-destructive))]",
outline:
"border-[hsl(var(--hu-border))] text-[hsl(var(--hu-foreground))] hover:bg-[hsl(var(--hu-accent))] hover:text-[hsl(var(--hu-accent-foreground))] focus-visible:ring-[hsl(var(--hu-ring))]",
ghost:
"border-transparent text-[hsl(var(--hu-foreground))] hover:bg-[hsl(var(--hu-accent))] hover:text-[hsl(var(--hu-accent-foreground))] focus-visible:ring-[hsl(var(--hu-ring))]",
},
size: {
sm: "h-5 px-2 gap-1",
default: "h-6 px-2.5 gap-1.5",
lg: "h-7 px-3 text-sm gap-1.5",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
},
);
export interface BadgeProps
extends React.HTMLAttributes<HTMLSpanElement>,
VariantProps<typeof badgeVariants> {
icon?: LucideIcon;
iconPosition?: "left" | "right";
}
function Badge({
className,
variant,
size,
icon: Icon,
iconPosition = "left",
children,
...props
}: BadgeProps) {
const iconSize = size === "sm" ? 12 : size === "lg" ? 14 : 12;
return (
<span
className={cn(badgeVariants({ variant, size }), className)}
{...props}
>
{Icon && iconPosition === "left" && (
<Icon size={iconSize} className="shrink-0" />
)}
{children}
{Icon && iconPosition === "right" && (
<Icon size={iconSize} className="shrink-0" />
)}
</span>
);
}
export { Badge, badgeVariants };
npx hextaui@latest add badge
pnpm dlx hextaui@latest add badge
yarn dlx hextaui@latest add badge
bun x hextaui@latest add badge
Usage
import { Badge } from "@/components/ui/Badge/Badge";
<Badge variant="default">Default</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="outline">Outline</Badge>
<Badge variant="ghost">Ghost</Badge>
<Badge variant="destructive">Destructive</Badge>
Examples
Variants
DefaultSecondaryOutlineGhostDestructive
<div className="flex gap-4 flex-wrap">
<Badge variant="default">Default</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="outline">Outline</Badge>
<Badge variant="ghost">Ghost</Badge>
<Badge variant="destructive">Destructive</Badge>
</div>
Sizes
SmallDefaultLarge
<div className="flex gap-4 flex-wrap items-center">
<Badge size="sm">Small</Badge>
<Badge size="default">Default</Badge>
<Badge size="lg">Large</Badge>
</div>
Status Indicators
DraftIn ProgressCompletedCancelled
<div className="flex gap-4 flex-wrap">
<Badge variant="ghost">Draft</Badge>
<Badge variant="secondary">In Progress</Badge>
<Badge variant="default">Completed</Badge>
<Badge variant="destructive">Cancelled</Badge>
</div>
Numbers and Counts
1
99+5
New<div className="flex gap-4 flex-wrap items-center">
<Badge variant="outline" size="sm">
1
</Badge>
<Badge variant="secondary">99+</Badge>
<Badge variant="destructive" size="sm">
5
</Badge>
<Badge variant="default">New</Badge>
</div>
Custom Styling
Rounded
Premium
Dashed
Bold<div className="flex gap-4 flex-wrap">
<Badge className="rounded-full">Rounded</Badge>
<Badge className="uppercase tracking-wider" size="sm">
Premium
</Badge>
<Badge variant="outline" className="border-dashed">
Dashed
</Badge>
<Badge className="font-bold">Bold</Badge>
</div>
With Icons
Featured
Verified
Warning
Premium
Continue
import { Star, CheckCircle, AlertTriangle, Zap, ArrowRight } from "lucide-react";
<div className="flex gap-4 flex-wrap">
<Badge icon={Star} variant="default">
Featured
</Badge>
<Badge icon={CheckCircle} variant="secondary" iconPosition="left">
Verified
</Badge>
<Badge icon={AlertTriangle} variant="destructive">
Warning
</Badge>
<Badge icon={Zap} variant="outline">
Premium
</Badge>
<Badge icon={ArrowRight} variant="ghost" iconPosition="right">
Continue
</Badge>
</div>
Icon Sizes
Small
Default
Large
import { Heart } from "lucide-react";
<div className="flex gap-4 flex-wrap items-center">
<Badge icon={Heart} variant="default" size="sm">
Small
</Badge>
<Badge icon={Heart} variant="secondary" size="default">
Default
</Badge>
<Badge icon={Heart} variant="outline" size="lg">
Large
</Badge>
</div>
Interactive Badges
Clickable
Remove
Focusable
<div className="flex gap-4 flex-wrap">
<Badge className="cursor-pointer" onClick={() => alert("Badge clicked!")}>
Clickable
</Badge>
<Badge
variant="outline"
className="cursor-pointer hover:border-red-500 hover:text-red-500"
>
Remove
</Badge>
<Badge variant="secondary" className="cursor-pointer" tabIndex={0}>
Focusable
</Badge>
</div>
Real-world Examples
Article:Published
React
Tutorial
User:Premium
Admin
Issue:Critical
Bug
P1
<div className="space-y-4">
<div className="flex items-center gap-2">
<span className="text-sm">Article:</span>
<Badge variant="default">Published</Badge>
<Badge variant="secondary" size="sm">
React
</Badge>
<Badge variant="outline" size="sm">
Tutorial
</Badge>
</div>
<div className="flex items-center gap-2">
<span className="text-sm">User:</span>
<Badge variant="secondary">Premium</Badge>
<Badge variant="ghost" size="sm">
Admin
</Badge>
</div>
<div className="flex items-center gap-2">
<span className="text-sm">Issue:</span>
<Badge variant="destructive">Critical</Badge>
<Badge variant="outline" size="sm">
Bug
</Badge>
<Badge variant="ghost" size="sm">
P1
</Badge>
</div>
</div>
Props
Prop | Type | Default |
---|---|---|
children? | ReactNode | undefined |
className? | string | undefined |
iconPosition? | "left" | "right" | "left" |
icon? | LucideIcon | undefined |
size? | "sm" | "default" | "lg" | "default" |
variant? | "default" | "secondary" | "destructive" | "outline" | "ghost" | "default" |
Edit on GitHub
Last updated on