{
  "name": "pad",
  "type": "registry:ui",
  "title": "Pad",
  "description": "A one-shot trigger in a grid: fire-and-forget, never touches transport state. The strike squishes (scale 0.94) and blooms the accent, decaying like a drum-pad LED, restartable mid-decay.",
  "dependencies": [
    "@candlelight-ds/tokens",
    "clsx",
    "tailwind-merge"
  ],
  "files": [
    {
      "path": "components/instruments/Pad.tsx",
      "type": "registry:ui",
      "content": "'use client'\n\n/**\n * Pad — a one-shot trigger. Fire-and-forget; never touches transport\n * state. Grid-agnostic: a console board row and a pad-set editor\n * arrange the same component.\n *\n * The strike flashes the pad — an accent bloom decaying like a struck\n * drum pad, proof the one-shot landed. Clicks flash locally; a parent\n * whose pads also fire from hotkeys bumps `hitSeq` so the board lights\n * up no matter which hand hit it.\n *\n * Use when: firing a one-shot over the bed (a sting, a stinger, a flash).\n * Don't use when: anything stateful (TransportButton) or commits\n * (CommitKey).\n */\n\nimport { forwardRef, useEffect, useRef } from 'react'\nimport { cn } from '@/lib/utils'\n\ninterface PadProps {\n  name: string\n  hotkey: string\n  onFire: () => void\n  /** Bump to flash the strike from outside (hotkey fires). */\n  hitSeq?: number\n  size?: 'rail' | 'board'\n  /** Copy (§9): the full a11y label — override from your copy module;\n   *  per-device where verbs differ (never tell a phone to \"press\"). */\n  ariaLabel?: string\n  className?: string\n}\n\n/** Restartable: removing and re-adding the class mid-animation replays\n *  it from the top, so rapid fire reads as rapid fire. */\nfunction flashPad(pad: HTMLButtonElement | null) {\n  if (!pad) return\n  pad.classList.remove('pad-hit')\n  void pad.offsetWidth\n  pad.classList.add('pad-hit')\n}\n\nexport const Pad = forwardRef<HTMLButtonElement, PadProps>(function Pad(\n  {\n    name,\n    hotkey,\n    onFire,\n    hitSeq,\n    size = 'rail',\n    ariaLabel = `${name} — press ${hotkey.toUpperCase()}`,\n    className,\n  },\n  ref\n) {\n  const innerRef = useRef<HTMLButtonElement | null>(null)\n\n  useEffect(() => {\n    if (hitSeq) flashPad(innerRef.current)\n  }, [hitSeq])\n\n  return (\n    <button\n      type=\"button\"\n      ref={(el) => {\n        innerRef.current = el\n        if (typeof ref === 'function') ref(el)\n        else if (ref) ref.current = el\n      }}\n      onClick={(event) => {\n        flashPad(event.currentTarget)\n        onFire()\n      }}\n      aria-label={ariaLabel}\n      className={cn(\n        'group relative flex shrink-0 flex-col items-center justify-center gap-0.5 overflow-hidden px-1',\n        'rounded-sm border border-hairline bg-fill-rest',\n        'transition-[color,background-color,border-color,transform] duration-instant',\n        'hover:border-brass-rim hover:bg-brass-fill active:translate-y-px active:bg-brass-held',\n        // Density (§2.6) is ambient: the pad is performance-native (48px\n        // rail key); under a bench ancestor it compacts.\n        size === 'rail'\n          ? 'h-12 w-[72px] [[data-density=bench]_&]:h-9 [[data-density=bench]_&]:w-14'\n          : 'h-20 w-full [[data-density=bench]_&]:h-14',\n        className\n      )}\n    >\n      <span\n        className={cn(\n          'max-w-full truncate font-medium text-ink-mute transition-colors group-hover:text-ink',\n          size === 'rail' ? 'text-micro' : 'text-meta'\n        )}\n      >\n        {name}\n      </span>\n      <span className=\"text-nano uppercase tracking-label text-ink-faint group-hover:text-brass/80 [[data-density=bench]_&]:hidden\">\n        {hotkey.toUpperCase()}\n      </span>\n    </button>\n  )\n})\n",
      "target": "components/instruments/Pad.tsx"
    }
  ],
  "meta": {
    "candlelight": {
      "category": "instrument",
      "gRules": [
        "G2",
        "G3"
      ],
      "useWhen": "Firing a one-shot over the bed — a sting, a stinger, a flash.",
      "dontUseWhen": "Anything stateful (TransportButton) or commits (CommitKey).",
      "states": [
        "resting",
        "hover (accent warm-up)",
        "striking (pad-hit bloom)",
        "board size (h-20 grid cell)"
      ],
      "keyboard": [
        {
          "keys": "printed hotkey",
          "does": "fires via the surface map; bump hitSeq so the pad flashes for the keyboard hand too"
        }
      ],
      "acceptanceTests": [
        "Rapid fire reads as rapid fire: the bloom restarts mid-decay (remove class → reflow → re-add).",
        "The bloom dies under prefers-reduced-motion."
      ]
    }
  },
  "registryDependencies": [
    "utils"
  ]
}