Skip to main content
Markdown

Badge

Badge is a small visual label used to highlight status, count, or category. It is a standalone component (no upstream Spar primitive) that follows Takeoff visual vocabulary.

Usage

import { Badge } from '@takeoff-ui/react-spar';
<Badge variant="success">Active</Badge>

Playground


function PlaygroundDemo() {
  return (
    <div className="flex flex-wrap justify-center gap-3">
      <Badge variant="primary">Primary</Badge>
      <Badge variant="success" appearance="filledLight">Active</Badge>
      <Badge variant="danger" rounded>3</Badge>
      <Badge variant="info" appearance="outlined">Info</Badge>
      <Badge variant="neutral" appearance="text">Draft</Badge>
    </div>
  );
}

render(<PlaygroundDemo />);

Variants


function VariantsDemo() {
  return (
    <div className="flex flex-wrap justify-center gap-3">
      <Badge variant="primary">Primary</Badge>
      <Badge variant="secondary">Secondary</Badge>
      <Badge variant="neutral">Neutral</Badge>
      <Badge variant="info">Info</Badge>
      <Badge variant="success">Success</Badge>
      <Badge variant="danger">Danger</Badge>
      <Badge variant="warning">Warning</Badge>
      <Badge variant="verified">Verified</Badge>
      <Badge variant="purple">Purple</Badge>
      <Badge variant="cyan">Cyan</Badge>
      <Badge variant="business">Business</Badge>
      <Badge variant="teal">Teal</Badge>
      <Badge variant="white">White</Badge>
      <Badge variant="dark">Dark</Badge>
    </div>
  );
}

render(<VariantsDemo />);

Appearances


function AppearancesDemo() {
  return (
    <div className="flex flex-wrap justify-center gap-3">
      <Badge appearance="filled">Filled</Badge>
      <Badge appearance="filledLight">Filled Light</Badge>
      <Badge appearance="outlined">Outlined</Badge>
      <Badge appearance="text">Text</Badge>
    </div>
  );
}

render(<AppearancesDemo />);

Sizes


function SizesDemo() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-3">
      <Badge size="small">Small</Badge>
      <Badge size="base">Base</Badge>
      <Badge size="large">Large</Badge>
    </div>
  );
}

render(<SizesDemo />);

Rounded


function TkDemo() {
  return (
    <div className="flex flex-wrap justify-center gap-3">
      <Badge rounded>12</Badge>
      <Badge variant="danger" rounded>99+</Badge>
      <Badge variant="success" rounded>New</Badge>
    </div>
  );
}

render(<TkDemo />);

Icons


function IconsDemo() {
  return (
    <div className="flex flex-wrap justify-center gap-3">
      <Badge variant="success" startContent={<CheckIconOutlinedRounded width={20} height={20} />}>Verified</Badge>
      <Badge variant="info" startContent={<PublicIconOutlinedRounded width={20} height={20} />}>Online</Badge>
      <Badge variant="danger" endContent={<BlockIconOutlinedRounded width={20} height={20} />}>Offline</Badge>
    </div>
  );
}

render(<IconsDemo />);

Dot


function DotDemo() {
  return (
    <div className="flex flex-wrap justify-center gap-3">
      <Badge variant="primary" dot />
      <Badge variant="danger" dot />
      <Badge variant="success" dot />
      <Badge variant="warning" dot />
      <Badge variant="info" dot />
    </div>
  );
}

render(<DotDemo />);

Float


function FloatDemo() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-8">
      <div className="relative">
        <div className="w-10 h-10 rounded-lg bg-neutral-200 flex items-center justify-center">
          <NotificationIconOutlinedRounded width={32} height={32} />
        </div>
        <Badge variant="danger" appearance="filledLight" size="large" rounded className="absolute -top-3 -right-3">3</Badge>
      </div>

      <div className="relative inline-flex">
        <div className="w-10 h-10 rounded-full bg-neutral-200 flex items-center justify-center">
          <PersonIconOutlinedRounded width={32} height={32} />
        </div>
        <Badge variant="success" dot className="absolute top-0 right-0" />
      </div>

      <div className="relative inline-flex">
        <div className="w-10 h-10 rounded-lg bg-neutral-200 flex items-center justify-center">
          <MailIconOutlinedRounded width={32} height={32} />
        </div>
        <Badge variant="info" size="small" className="absolute -top-1.5 -right-1.5">99</Badge>
      </div>
    </div>
  );
}

render(<FloatDemo />);

API Reference

Badge

Props

NameTypeDefaultDescription
childrenReact.ReactNode-Badge content.
variantBadgeVariant'primary'Color variant.
appearanceBadgeAppearance'filled'Visual appearance.
sizeBadgeSize'base'Size scale.
roundedbooleanfalseRenders a pill-shaped badge with fully rounded corners.
dotbooleanfalseRenders a minimal colored dot (8×8px) with no content. When true, children, startContent, and endContent are ignored.
startContentReact.ReactNode-Content rendered before children — typically an icon.
endContentReact.ReactNode-Content rendered after children.
classNamesPartial<Record<BadgeSlot, string>>-Per-slot extra classes.
slotPropsPartial<Record<BadgeSlot, React.HTMLAttributes<HTMLElement>>>-Per-slot HTML-attribute overrides.
classNamestring-Appends custom classes to the root slot.

Data attributes

AttributeApplied whenPurpose
data-slot="root"AlwaysStable selector for wrapper styling on the root slot.
data-variantAlwaysReflects the resolved variant prop for theme recipe scoping.
data-typeAlwaysReflects the resolved appearance prop for theme recipe scoping.
data-sizeWhen dot is falseReflects the resolved size prop for theme recipe scoping.
data-roundedWhen rounded is trueStyling hook for the pill-shaped state.
data-dotWhen dot is trueStyling hook for the minimal dot mode.

Type Definitions

NameDefinition
BadgeVariant| 'primary' | 'secondary' | 'neutral' | 'info' | 'success' | 'danger' | 'warning' | 'verified' | 'purple' | 'cyan' | 'business' | 'teal' | 'white' | 'dark'
BadgeAppearance'filled' | 'filledLight' | 'outlined' | 'text'
BadgeSize'small' | 'base' | 'large'
BadgeSlot'root' | 'label' | 'icon'