{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "badge",
  "title": "Badge",
  "author": "AniBT <https://anibt.net>",
  "description": "AniBT tags (neutral, resolution, language, status words), die-cut stickers (paper, candy, water), counts, plus StatusBadge (dot + word) and StatusDot.",
  "dependencies": [
    "class-variance-authority",
    "radix-ui"
  ],
  "registryDependencies": [
    "@anibt/theme"
  ],
  "files": [
    {
      "path": "registry/anibt/ui/badge.tsx",
      "content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\n\n/**\n * Badge, StatusBadge and StatusDot — the AniBT 「贴纸手账」 label family.\n *\n * `Badge`:\n * - tags (20px, radius 6): `default` (neutral — a spec, a category), `res`\n *   (blue: resolution, format, time — in the round face), `lang` (pink:\n *   language, subtitles), and the status words `success` / `warning` /\n *   `destructive` (mint / amber / red, no dot).\n * - stickers (die-cut white rim, tilted by `tilt`): `sticker`, and the filled\n *   `candy` and `water`. A label stuck on — use sparingly.\n * - counts (20px pill): `count` (candy) and `count-quiet` (neutral).\n * - `secondary` and `outline` exist only so code written against shadcn's\n *   badge keeps compiling; both are the neutral tag.\n *\n * `StatusBadge` is a state with its word and a 6px dot: ok (mint), run (blue,\n * the dot blinks), fail (red), warn (amber), mute (grey), on (pink). The word\n * is required — colour never speaks alone.\n *\n * `StatusDot` is the label-less 6px dot beside copy that already says the\n * state (a legend, a rail count). It is `aria-hidden`.\n */\nconst badgeVariants = cva(\n  \"inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:outline-solid [&>svg]:pointer-events-none [&>svg]:size-3\",\n  {\n    variants: {\n      variant: {\n        default: \"anibt-tag\",\n        secondary: \"anibt-tag\",\n        outline: \"anibt-tag\",\n        res: \"anibt-tag anibt-tag-res\",\n        lang: \"anibt-tag anibt-tag-lang\",\n        success: \"anibt-tag anibt-tag-ok\",\n        warning: \"anibt-tag anibt-tag-warn\",\n        destructive: \"anibt-tag anibt-tag-danger\",\n        sticker: \"anibt-sticker\",\n        candy: \"anibt-sticker anibt-sticker-candy\",\n        water: \"anibt-sticker anibt-sticker-water\",\n        count: \"anibt-count\",\n        \"count-quiet\": \"anibt-count anibt-count-quiet\",\n      },\n      /** Specs and figures take the round face; a word takes the body face. */\n      face: {\n        spec: \"anibt-num\",\n        text: \"\",\n      },\n      size: {\n        default: \"\",\n        /** A 24px tag for a header row. */\n        lg: \"h-6 px-2.5\",\n      },\n    },\n    defaultVariants: {\n      variant: \"default\",\n      face: \"spec\",\n      size: \"default\",\n    },\n  }\n)\n\ntype BadgeProps = React.ComponentProps<\"span\"> &\n  VariantProps<typeof badgeVariants> & {\n    asChild?: boolean\n    /** Tilt in degrees for the sticker variants (A uses −4 … 4). */\n    tilt?: number\n  }\n\nfunction Badge({ className, variant, face, size, asChild = false, tilt, style, ...props }: BadgeProps) {\n  const Comp = asChild ? Slot.Root : \"span\"\n  const tiltStyle =\n    tilt === undefined ? style : ({ ...style, \"--anibt-tilt\": `${tilt}deg` } as React.CSSProperties)\n\n  return (\n    <Comp\n      data-slot=\"badge\"\n      data-variant={variant ?? \"default\"}\n      className={cn(badgeVariants({ variant, face, size }), className)}\n      style={tiltStyle}\n      {...props}\n    />\n  )\n}\n\nconst statusBadgeVariants = cva(\"anibt-status\", {\n  variants: {\n    tone: {\n      ok: \"anibt-status-ok\",\n      run: \"anibt-status-run\",\n      fail: \"anibt-status-fail\",\n      warn: \"anibt-status-warn\",\n      mute: \"anibt-status-mute\",\n      on: \"anibt-status-on\",\n    },\n  },\n  defaultVariants: {\n    tone: \"mute\",\n  },\n})\n\ntype StatusBadgeProps = React.ComponentProps<\"span\"> &\n  VariantProps<typeof statusBadgeVariants> & {\n    /** The word that names the state. */\n    children: React.ReactNode\n  }\n\nfunction StatusBadge({ className, tone, ...props }: StatusBadgeProps) {\n  return (\n    <span\n      data-slot=\"status-badge\"\n      data-tone={tone ?? \"mute\"}\n      className={cn(statusBadgeVariants({ tone }), className)}\n      {...props}\n    />\n  )\n}\n\nconst statusDotVariants = cva(\"anibt-dot\", {\n  variants: {\n    variant: {\n      default: \"\",\n      ok: \"anibt-dot-ok\",\n      warn: \"anibt-dot-warn\",\n      danger: \"anibt-dot-danger\",\n      time: \"anibt-dot-time\",\n      hollow: \"anibt-dot-hollow\",\n      mute: \"anibt-dot-mute\",\n    },\n  },\n  defaultVariants: {\n    variant: \"default\",\n  },\n})\n\ntype StatusDotProps = Omit<React.ComponentProps<\"span\">, \"children\"> &\n  VariantProps<typeof statusDotVariants>\n\nfunction StatusDot({ className, variant, ...props }: StatusDotProps) {\n  return (\n    <span\n      data-slot=\"status-dot\"\n      aria-hidden=\"true\"\n      className={cn(statusDotVariants({ variant }), className)}\n      {...props}\n    />\n  )\n}\n\nexport { Badge, badgeVariants, StatusBadge, statusBadgeVariants, StatusDot, statusDotVariants }\nexport type { BadgeProps, StatusBadgeProps, StatusDotProps }\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "display"
  ],
  "type": "registry:ui"
}