{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "artifact-perk",
  "title": "Artifact perk",
  "description": "A seasonal-artifact perk tile — one square cell of the in-game artifact grid: teal-filled when the perk is active, teal-outlined when it's unlocked but unpicked, and dimmed while its tier is still locked.",
  "dependencies": [
    "@engram/core"
  ],
  "registryDependencies": [
    "@engram/bungie-image",
    "@engram/cn",
    "@engram/item-hover-card",
    "@engram/tokens"
  ],
  "files": [
    {
      "path": "src/components/artifact-perk.tsx",
      "content": "import type { ImageRef } from \"@engram/core\";\nimport type { ButtonHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../lib/cn.js\";\nimport { BungieImage } from \"./bungie-image.js\";\nimport { ItemHoverCard } from \"./item-hover-card.js\";\n\nexport type ArtifactPerkState = \"active\" | \"unlocked\" | \"locked\";\n\nexport interface ArtifactPerkProps\n  extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"name\"> {\n  /** The perk glyph (the perk item definition's icon). */\n  icon?: ImageRef;\n  /** Perk name — the accessible label. */\n  name: string;\n  /** `active` = picked (teal fill), `unlocked` = available (teal outline),\n   *  `locked` = not yet reachable (dimmed). */\n  state?: ArtifactPerkState;\n  /** Pixel size (square). */\n  size?: number;\n  /** Inspect content revealed on hover (e.g. a {@link PlugPopup}). */\n  popup?: ReactNode;\n  /** Fired on click (toggle/pick the perk). */\n  onPick?: () => void;\n}\n\n// The three in-game tile treatments, all built on the artifact teal token.\nconst STATE: Record<ArtifactPerkState, string> = {\n  active:\n    \"border-[color-mix(in_srgb,var(--engram-artifact)_55%,white)] bg-engram-artifact\",\n  unlocked:\n    \"border-engram-artifact bg-[color-mix(in_srgb,var(--engram-artifact)_18%,transparent)]\",\n  locked:\n    \"border-[color-mix(in_srgb,var(--engram-artifact)_30%,transparent)] bg-[color-mix(in_srgb,var(--engram-artifact)_8%,transparent)]\",\n};\n\n/**\n * A seasonal-artifact perk tile — one square cell of the in-game artifact\n * grid: teal-filled when the perk is active, teal-outlined when it's unlocked\n * but unpicked, and dimmed while its tier is still locked. Hovering draws the\n * game's white selection frame and reveals the inspect `popup`.\n */\nexport function ArtifactPerk({\n  icon,\n  name,\n  state = \"unlocked\",\n  size = 48,\n  popup,\n  onPick,\n  className,\n  ...props\n}: ArtifactPerkProps) {\n  const tile = (\n    <button\n      type=\"button\"\n      onClick={onPick}\n      title={name}\n      aria-label={name}\n      aria-pressed={state === \"active\"}\n      className={cn(\n        \"grid shrink-0 place-items-center rounded-[3px] border transition-[border-color,outline-color]\",\n        STATE[state],\n        // The in-game selection frame: the border goes white and a detached\n        // outer ring appears.\n        \"hover:border-white/90 hover:outline-2 hover:outline-offset-2 hover:outline-white/70\",\n        onPick && \"cursor-pointer\",\n        className,\n      )}\n      style={{ width: size, height: size }}\n      {...props}\n    >\n      {icon ? (\n        <BungieImage\n          src={icon}\n          alt=\"\"\n          aria-hidden\n          className={cn(\n            \"h-full w-full object-contain p-[12%]\",\n            state === \"locked\" && \"opacity-45\",\n          )}\n        />\n      ) : null}\n    </button>\n  );\n\n  // The tile is itself a <button>, so the hover wrapper renders a <span> to\n  // avoid nesting interactive elements (same pattern as AbilitySlot).\n  if (popup) {\n    return (\n      <ItemHoverCard as=\"span\" popup={popup}>\n        {tile}\n      </ItemHoverCard>\n    );\n  }\n  return tile;\n}\n",
      "type": "registry:component",
      "target": "components/engram/artifact-perk.tsx"
    }
  ],
  "meta": {
    "level": "component"
  },
  "docs": "Extend without forking: edit the copied source, use `asChild` (Radix Slot) to change the rendered element, pass the typed `annotations` prop for curated data (verdict/tags/per-plug), or use slot / render-prop props for arbitrary content. Requires the @engram/tokens theme (--engram-* CSS variables).",
  "categories": [
    "loadout"
  ],
  "type": "registry:component"
}