Badge (Tailwind)

PreviousNext

A small count and labeling component.

Docs
roiuiitem

Preview

Loading preview…
registry/brook/tailwind/ui/badge.tsx
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";

const badgeVariants = cva(
  [
    "inline-flex items-center justify-center border-[0.5px] border-border/80 font-normal",
    "w-fit flex-shrink-0 gap-1.5 whitespace-nowrap",
    "overflow-hidden transition-[color,box-shadow] duration-150 ease-in-out",
    "[&_svg]:pointer-events-none",
    "focus-visible:border-ring focus-visible:shadow-[0_0_0_3px_var(--ring),inset_0_0_0_1px_var(--ring)]",
    "aria-[invalid=true]:border-destructive aria-[invalid=true]:shadow-[0_0_0_1px_var(--destructive)]",
  ],
  {
    variants: {
      variant: {
        default:
          "selection:!bg-[oklch(0_0_0)] selection:!text-foreground [&_*]:selection:!bg-[oklch(0_0_0)] [&_*]:selection:!text-foreground [.light_&]:selection:!bg-white [.light_&]:selection:!text-black [.light_&_*]:selection:!bg-white [.light_&_*]:selection:!text-black [[data-theme='light']_&]:selection:!bg-white [[data-theme='light']_&]:selection:!text-black [[data-theme='light']_&_*]:selection:!bg-white [[data-theme='light']_&_*]:selection:!text-black bg-foreground text-primary-foreground",
        secondary: "border-transparent bg-[var(--secondary)] text-secondary-foreground",
        destructive: [
          "border-transparent bg-[var(--secondary)] text-destructive",
          "focus-visible:shadow-[0_0_0_3px_var(--destructive),inset_0_0_0_1px_var(--destructive)]",
        ],
        success: [
          "border-transparent bg-[var(--secondary)] text-success",
          "focus-visible:shadow-[0_0_0_3px_var(--success),inset_0_0_0_1px_var(--success)]",
        ],
        info: [
          "border-transparent bg-[var(--secondary)] text-info",
          "focus-visible:shadow-[0_0_0_3px_var(--info),inset_0_0_0_1px_var(--info)]",
        ],
        outline: "border-border bg-transparent text-foreground hover:bg-card",
      },
      size: {
        sm: "rounded-[var(--radius)] px-1.5 py-px text-[0.625rem] leading-[15px]",
        md: "rounded-[var(--radius)] px-2 py-0.5 text-xs leading-[14px]",
        lg: "rounded-[var(--radius-lg)] px-3 py-1 text-sm",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "md",
    },
  }
);

/**
 * Badge component for displaying labels, tags, and status indicators.
 *
 * @param variant - The visual style of the badge
 *   - `"default"` - Standard badge appearance
 *   - `"secondary"` - Secondary color scheme
 *   - `"destructive"` - Red color scheme for errors or warnings
 *   - `"outline"` - Outlined badge with transparent background
 *   - `"success"` - Green color scheme for success states
 *   - `"info"` - Blue color scheme for informational states
 * @param size - The size of the badge
 *   - `"sm"` - Small badge
 *   - `"md"` - Medium badge (default)
 *   - `"lg"` - Large badge
 * @param className - Optional CSS class names
 *
 * @example
 * ```tsx
 * // Standard badge
 * <Badge>New</Badge>
 *
 * // Badge with variant and size
 * <Badge variant="success" size="lg">Active</Badge>
 *
 * // Badge with icon
 * <Badge variant="destructive">
 *   <BadgeIcon>
 *     <AlertIcon />
 *   </BadgeIcon>
 *   Error
 * </Badge>
 * ```
 */
function Badge({
  className,
  variant,
  size,
  ...props
}: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants>) {
  return <span className={cn(badgeVariants({ variant, size }), className)} data-slot="badge" {...props} />;
}

/**
 * BadgeIcon component for displaying icons within a Badge.
 *
 * @param className - Optional CSS class names
 *
 * @example
 * ```tsx
 * <Badge>
 *   <BadgeIcon>
 *     <StarIcon />
 *   </BadgeIcon>
 *   Featured
 * </Badge>
 * ```
 */
function BadgeIcon({ className, ...props }: React.ComponentProps<"span">) {
  return (
    <span
      className={cn("mr-1 inline-flex flex-shrink-0 items-center justify-center rounded-full p-0.5", className)}
      data-slot="badge-icon"
      {...props}
    />
  );
}

export { Badge, BadgeIcon };

Installation

npx shadcn@latest add @roiui/badge-tailwind

Usage

import { BadgeTailwind } from "@/components/badge-tailwind"
<BadgeTailwind />