Badge

A badge is a small status component that can be used to display a status or a count.

Badge
export const Example = () => {
  return <Badge>Badge</Badge>;
};

Installation

If you haven't included Piksel UI in your project, include it first. You can check the installation page.

Source code

Copy the following source code and add it to your project.

import { cn } from "@/utils/cn";
import { Slot } from "@radix-ui/react-slot";
import { forwardRef, HTMLAttributes } from "react";
import { tv, VariantProps } from "tailwind-variants";

export const badgeDisplayName = "Badge";

export type BadgeProps = HTMLAttributes<HTMLDivElement> &
  VariantProps<typeof badgeStyles> & {
    /**
     * If true, the badge will be rendered as a child component
     */
    asChild?: boolean;
  };

/**
 * @name Badge
 * @description The Badge component is
 */
export const Badge = forwardRef<HTMLDivElement, BadgeProps>((props, ref) => {
  const {
    asChild,
    variant,
    color,
    size,
    radius,
    truncate,
    className,
    children,
    ...rest
  } = props;

  const componentClassNames = badgeStyles({
    variant,
    color,
    size,
    radius,
    truncate,
    className,
  });

  const Component = asChild ? Slot : "div";

  return (
    <Component className={cn(componentClassNames)} {...rest} ref={ref}>
      {children}
    </Component>
  );
});
Badge.displayName = badgeDisplayName;

export const badgeStyles = tv({
  /**
   * Base styles of the badge
   */
  base: [
    "relative inline-flex items-center justify-center no-underline outline-0",
    "font-medium ring-0 ring-offset-0 transition-all flex-shrink-0 max-w-full whitespace-nowrap overflow-hidden",
    "focus-visible:ring-2 focus-visible:ring-offset-2",
    "disabled:opacity-75 disabled:cursor-not-allowed",
  ],
  variants: {
    /**
     * Variant prop of the badge
     */
    variant: {
      filled: "border",
      soft: "",
      outline: "border focus-visible:ring-transparent",
    },
    /**
     * Color prop of the badge
     */
    color: {
      blue: "ring-blue-300 border-blue-600",
      red: "ring-red-300 border-red-600",
      indigo: "ring-indigo-300 border-indigo-600",
      green: "ring-green-300 border-green-600",
      yellow: "ring-yellow-200 border-yellow-500",
      zinc: "ring-zinc-300 border-zinc-600",
      white: "ring-zinc-50 border-zinc-50",
      black: "ring-zinc-400 border-zinc-900",
    },
    /**
     * Size prop of the badge
     */
    size: {
      sm: "px-1 py-0 text-sm gap-0.5",
      md: "px-1.5 py-0.5 text-sm gap-1",
      lg: "px-2 py-1 text-sm gap-1.5",
    },
    radius: {
      none: "rounded-none",
      sm: "rounded-sm",
      md: "rounded-md",
      lg: "rounded-lg",
      full: "rounded-full",
    },
    truncate: {
      true: "truncate line-clamp-1",
    },
  },
  compoundVariants: [
    /* -------------------------------------------------------------------------- */
    /*                             Variants and colors                            */
    /* -------------------------------------------------------------------------- */
    /* -------------------------------------------------------------------------- */
    /*                               Filled variant                               */
    /* -------------------------------------------------------------------------- */
    {
      variant: "filled",
      color: "blue",
      className: "bg-blue-500 text-white hover:text-white",
    },
    {
      variant: "filled",
      color: "red",
      className: "bg-red-500 text-white hover:text-white",
    },
    {
      variant: "filled",
      color: "indigo",
      className: "bg-indigo-500 text-white hover:text-white",
    },
    {
      variant: "filled",
      color: "green",
      className: "bg-green-500 text-white hover:text-white",
    },
    {
      variant: "filled",
      color: "yellow",
      className: "bg-yellow-400 text-black hover:text-black",
    },
    {
      variant: "filled",
      color: "zinc",
      className: "bg-zinc-500 text-white hover:text-white",
    },
    {
      variant: "filled",
      color: "white",
      className: "bg-zinc-50 text-zinc-950 hover:text-zinc-950",
    },
    {
      variant: "filled",
      color: "black",
      className: "bg-zinc-950 text-white hover:text-white",
    },
    /* -------------------------------------------------------------------------- */
    /*                                Soft variant                                */
    /* -------------------------------------------------------------------------- */
    {
      variant: "soft",
      color: "blue",
      className: "bg-blue-100 text-blue-600 hover:text-blue-600",
    },
    {
      variant: "soft",
      color: "red",
      className: "bg-red-100 text-red-600 hover:text-red-600",
    },
    {
      variant: "soft",
      color: "indigo",
      className: "bg-indigo-100 text-indigo-600 hover:text-indigo-600",
    },
    {
      variant: "soft",
      color: "green",
      className: "bg-green-100 text-green-600 hover:text-green-600",
    },
    {
      variant: "soft",
      color: "yellow",
      className: "bg-yellow-100 text-yellow-600 hover:text-yellow-600",
    },
    {
      variant: "soft",
      color: "zinc",
      className: "bg-zinc-100 text-zinc-600 hover:text-zinc-600",
    },
    {
      variant: "soft",
      color: "white",
      className: "bg-white text-zinc-950 hover:text-zinc-950",
    },
    {
      variant: "soft",
      color: "black",
      className: "bg-zinc-200 text-zinc-600",
    },
    /* -------------------------------------------------------------------------- */
    /*                               Outline variant                              */
    /* -------------------------------------------------------------------------- */
    {
      variant: "outline",
      color: "blue",
      className: ["text-blue-500 outline-blue-500"],
    },
    {
      variant: "outline",
      color: "red",
      className: ["text-red-500 outline-red-500"],
    },
    {
      variant: "outline",
      color: "indigo",
      className: ["text-indigo-500 outline-indigo-500"],
    },
    {
      variant: "outline",
      color: "green",
      className: ["text-green-500 outline-green-500"],
    },
    {
      variant: "outline",
      color: "yellow",
      className: ["text-yellow-600 outline-yellow-500"],
    },
    {
      variant: "outline",
      color: "zinc",
      className: ["text-zinc-500 outline-zinc-500"],
    },
    {
      variant: "outline",
      color: "white",
      className: ["text-zinc-500 outline-zinc-500"],
    },
    {
      variant: "outline",
      color: "black",
      className: ["text-zinc-950 outline-zinc-950"],
    },
  ],
  defaultVariants: {
    variant: "filled",
    color: "blue",
    size: "md",
    radius: "md",
  },
});

Props

The Badge component has the following props.

PropTypeDefaultDescription
asChild?booleanfalseThe component used for the root node.
variant?'filled' | 'soft' | 'outline''filled'The variant of the badge.
color?'blue' | 'red' | 'indigo' | 'green' | 'yellow' | 'zinc' | 'white' | 'black''blue'The color of the badge.
size?'sm' | 'md' | 'lg''md'The size of the badge.
radius?'none' | 'sm' | 'md' | 'lg' | 'full''md'The border radius of the badge.
truncate?booleanfalseWhether the badge text is truncated.