Agents (llms.txt)
Octocat

Badge

A Badge component with the possibility of adding an icon and a status

Up to date
import { PackageIcon } from "@phosphor-icons/react/dist/ssr";

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

export default function BadgePreview() {
  return (
    <Badge>
      <Badge.Icon>
        <PackageIcon />
      </Badge.Icon>
      <span>Up to date</span>
      <Badge.Status className="bg-emerald-500" />
    </Badge>
  );
}

Dependencies

Source Code

import type { VariantProps } from "cva";

import { Slot } from "@/components/slot";
import { cn, cva } from "@/lib/utils/classnames";

const badgeStyle = cva({
  base: "inline-flex items-center gap-1 rounded-full font-semibold leading-none ring-1 ring-inset [&>[data-badge-icon]:first-child]:-ml-0.5 [&>[data-badge-icon]:last-child]:-mr-0.5",
  variants: {
    variant: {
      neutral: "bg-background text-foreground/80 ring-foreground/10",
      success: "bg-success/10 text-success ring-success/20",
      error: "bg-error/10 text-error ring-error/20",
      warning: "bg-warning/10 text-warning ring-warning/20",
      info: "bg-info/10 text-info ring-info/20",
    },
    size: {
      md: "h-6 px-2.5 text-sm",
      sm: "h-5 px-2 text-xs",
      xs: "h-4 px-1.5 text-2xs",
    },
  },
  defaultVariants: {
    size: "md",
  },
});

interface BadgeProps extends React.ComponentPropsWithRef<"div"> {
  variant?: VariantProps<typeof badgeStyle>["variant"];
  size?: VariantProps<typeof badgeStyle>["size"];
  asChild?: boolean;
}

const Badge = ({
  ref,
  children,
  variant = "neutral",
  size = "md",
  className,
  asChild,
  ...rest
}: BadgeProps) => {
  const Comp = asChild ? Slot : "div";

  return (
    <Comp ref={ref} className={cn(badgeStyle({ variant, size }), className)} {...rest}>
      {children}
    </Comp>
  );
};

const BadgeIcon = ({ children, className, ...rest }: React.ComponentPropsWithRef<"div">) => {
  return (
    <div data-badge-icon className={cn("flex items-center justify-center", className)} {...rest}>
      {children}
    </div>
  );
};

const BadgeStatus = ({
  className,
  ...rest
}: Omit<React.ComponentPropsWithRef<"div">, "children">) => {
  return (
    <div
      className={cn("mx-0.5 size-1.5 rounded-full bg-current first:ml-0 last:mr-0", className)}
      {...rest}
    />
  );
};

const CompoundBadge = Object.assign(Badge, {
  Icon: BadgeIcon,
  Status: BadgeStatus,
});

export { CompoundBadge as Badge };

Anatomy

          <Badge>
  <Badge.Icon />
  <Badge.Status />
</Badge>
        

API Reference

Badge

Extends the div element.

PropDefaultType
variant"neutral""neutral""success""error""warning""info"
size"md""xs""sm""md"
asChild-boolean

Badge.Icon

Extends the div element.

Badge.Status

Extends the div element.

Examples

Variants

Neutral
Success
Error
Warning
Info
import { Badge } from "@/components/badge";

export default function BadgeVariantsPreview() {
  return (
    <div className="flex flex-wrap items-center gap-2">
      <Badge variant="neutral">Neutral</Badge>
      <Badge variant="success">Success</Badge>
      <Badge variant="error">Error</Badge>
      <Badge variant="warning">Warning</Badge>
      <Badge variant="info">Info</Badge>
    </div>
  );
}

Sizes

Extra small
Small
Medium
import { Badge } from "@/components/badge";

export default function BadgeSizesPreview() {
  return (
    <div className="flex flex-wrap items-center gap-2">
      <Badge size="xs">Extra small</Badge>
      <Badge size="sm">Small</Badge>
      <Badge size="md">Medium</Badge>
    </div>
  );
}

With icon and status

Up to date
import { PackageIcon } from "@phosphor-icons/react/dist/ssr";

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

export default function BadgePreview() {
  return (
    <Badge>
      <Badge.Icon>
        <PackageIcon />
      </Badge.Icon>
      <span>Up to date</span>
      <Badge.Status className="bg-emerald-500" />
    </Badge>
  );
}

Best Practices

  1. Usage:

    • Use appropriate variants for context
    • Keep content concise
    • Consider icon visibility at small sizes
  2. Accessibility:

    • Ensure sufficient color contrast
    • Provide clear meaning through text

Previous

Avatar

Next

Breadcrumb