Fiber UI LogoFiberUI

Badge

Display a badge or status indicator.

Basic Usage

Badge
import { Badge } from "@repo/ui/components/badge";

/* BASIC USAGE EXAMPLE */
export const Example1 = () => {
    return <Badge>Badge</Badge>;
};

Variants

DefaultSecondaryDestructiveOutline
import { Badge } from "@repo/ui/components/badge";

/* BADGE VARIANTS EXAMPLE */
export const Example2 = () => {
    return (
        <div className="flex flex-wrap gap-2">
            <Badge variant="default">Default</Badge>
            <Badge variant="secondary">Secondary</Badge>
            <Badge variant="destructive">Destructive</Badge>
            <Badge variant="outline">Outline</Badge>
        </div>
    );
};

With Icons

SuccessErrorWarningInfo
import { Badge } from "@repo/ui/components/badge";
import { Check, X, AlertTriangle, Info } from "lucide-react";

/* BADGE WITH ICONS EXAMPLE */
export const Example3 = () => {
    return (
        <div className="flex flex-wrap gap-2">
            <Badge>
                <Check />
                Success
            </Badge>
            <Badge variant="destructive">
                <X />
                Error
            </Badge>
            <Badge variant="secondary">
                <AlertTriangle />
                Warning
            </Badge>
            <Badge variant="outline">
                <Info />
                Info
            </Badge>
        </div>
    );
};

With Loading Spinner

SyncingLoading...ProcessingRefreshing
import { Badge } from "@repo/ui/components/badge";
import { RefreshCw, Loader2 } from "lucide-react";

/* BADGE WITH LOADING SPINNER - SYNCING EXAMPLE */
export const Example4 = () => {
    return (
        <div className="flex flex-wrap items-center gap-3">
            <Badge variant="secondary">
                <Loader2 className="animate-spin" />
                Syncing
            </Badge>
            <Badge variant="outline">
                <Loader2 className="animate-spin" />
                Loading...
            </Badge>
            <Badge>
                <Loader2 className="animate-spin" />
                Processing
            </Badge>
            <Badge variant="secondary">
                <RefreshCw className="animate-spin" />
                Refreshing
            </Badge>
        </div>
    );
};

As Notification Indicator

3
12
5
2
import { Badge } from "@repo/ui/components/badge";
import { Button } from "@repo/ui/components/button";
import { Bell, Mail, MessageSquare, ShoppingCart } from "lucide-react";

/* BADGE AS NOTIFICATION INDICATOR */
export const Example5 = () => {
    return (
        <div className="flex flex-wrap items-center gap-4">
            <div className="relative">
                <Button size="icon" variant="outline">
                    <Bell className="size-4" />
                </Button>
                <Badge className="absolute -right-1 -top-1 size-5 p-0 text-[10px]">
                    3
                </Badge>
            </div>
            <div className="relative">
                <Button size="icon" variant="outline">
                    <Mail className="size-4" />
                </Button>
                <Badge className="absolute -right-1 -top-1 size-5 p-0 text-[10px]">
                    12
                </Badge>
            </div>
            <div className="relative">
                <Button size="icon" variant="outline">
                    <MessageSquare className="size-4" />
                </Button>
                <Badge
                    variant="destructive"
                    className="absolute -right-1 -top-1 size-5 p-0 text-[10px]"
                >
                    5
                </Badge>
            </div>
            <div className="relative">
                <Button size="icon" variant="outline">
                    <ShoppingCart className="size-4" />
                </Button>
                <Badge
                    variant="secondary"
                    className="absolute -right-1 -top-1 size-5 p-0 text-[10px]"
                >
                    2
                </Badge>
            </div>
        </div>
    );
};

Component Code

import * as React from "react";
import { tv, type VariantProps, cn } from "tailwind-variants";

const badgeStyles = tv({
    base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden whitespace-nowrap rounded-full border px-2 py-0.5 text-xs font-medium transition-[color,box-shadow] focus-visible:ring-[3px] [&>svg]:pointer-events-none [&>svg]:size-3",
    variants: {
        variant: {
            default:
                "bg-primary text-primary-foreground [a&]:hover:bg-primary/90 border-transparent",
            secondary:
                "bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90 border-transparent",
            destructive:
                "bg-destructive [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60 border-transparent text-white",
            outline:
                "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
        },
    },
    defaultVariants: {
        variant: "default",
    },
});

interface BadgeProps
    extends React.ComponentProps<"span">,
        VariantProps<typeof badgeStyles> {}

export const Badge = ({ className, variant, ...props }: BadgeProps) => {
    return (
        <span
            data-slot="badge"
            className={cn(badgeStyles({ variant }), className)}
            {...props}
        />
    );
};

export { badgeStyles };