{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"badge-preview","type":"registry:component","title":"Badge Preview","description":"Visual badge preview with live image rendering and optional copyable code snippet. Ideal for documentation pages, badge builders, and app UIs.","dependencies":[],"registryDependencies":[],"categories":["badges","docs"],"files":[{"path":"registry/badge-preview/badge-preview.tsx","type":"registry:component","content":"/**\n * shieldcn\n * BadgePreview\n * by Justin Levine\n * shieldcn.dev\n *\n * Visual badge preview component for documentation pages and app UIs.\n * Renders a live badge image with an optional copyable code snippet below.\n *\n * Props:\n * - src: badge image URL\n * - alt?: accessible alt text (default \"badge\")\n * - code?: code snippet to display below the badge\n * - label?: optional label above the badge\n * - mode?: background mode (\"dark\" | \"light\", default \"dark\")\n * - className?: additional class names\n */\n\n\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/lib/utils\"\n\ninterface BadgePreviewProps extends React.ComponentProps<\"div\"> {\n  /** Badge image URL. */\n  src: string\n  /** Accessible alt text. @default \"badge\" */\n  alt?: string\n  /** Code snippet to display below the badge. */\n  code?: string\n  /** Optional label above the badge. */\n  label?: string\n  /** Background mode. @default \"dark\" */\n  mode?: \"dark\" | \"light\"\n  /** Additional class names. */\n  className?: string\n}\n\nfunction BadgePreview({\n  src,\n  alt = \"badge\",\n  code,\n  label,\n  mode = \"dark\",\n  className,\n  ...props\n}: BadgePreviewProps) {\n  const [copied, setCopied] = React.useState(false)\n\n  const handleCopy = React.useCallback(() => {\n    if (!code) return\n    navigator.clipboard.writeText(code)\n    setCopied(true)\n    setTimeout(() => setCopied(false), 2000)\n  }, [code])\n\n  return (\n    <div\n      data-slot=\"badge-preview\"\n      className={cn(\n        \"overflow-hidden rounded-lg border border-border\",\n        className\n      )}\n      {...props}\n    >\n      {label && (\n        <div className=\"border-b border-border px-4 py-2\">\n          <span className=\"text-xs font-medium text-muted-foreground\">\n            {label}\n          </span>\n        </div>\n      )}\n\n      <div\n        className={cn(\n          \"flex items-center justify-center px-6 py-8\",\n          mode === \"dark\" ? \"bg-zinc-950\" : \"bg-zinc-100\"\n        )}\n      >\n        {/* eslint-disable-next-line @next/next/no-img-element */}\n        <img\n          src={src}\n          alt={alt}\n          className=\"inline-block max-w-full\"\n          loading=\"lazy\"\n          decoding=\"async\"\n        />\n      </div>\n\n      {code && (\n        <div className=\"relative border-t border-border bg-muted/30\">\n          <pre className=\"overflow-x-auto px-4 py-3\">\n            <code className=\"text-xs text-muted-foreground\">{code}</code>\n          </pre>\n          <button\n            type=\"button\"\n            onClick={handleCopy}\n            className={cn(\n              \"absolute right-2 top-2 rounded-md border border-border px-2 py-1 text-[10px] font-medium transition-colors\",\n              copied\n                ? \"bg-primary text-primary-foreground\"\n                : \"bg-background text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n            )}\n          >\n            {copied ? \"Copied\" : \"Copy\"}\n          </button>\n        </div>\n      )}\n    </div>\n  )\n}\n\nexport { BadgePreview }\nexport type { BadgePreviewProps }\n"}]}