{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "claude-slash-menu",
  "title": "Claude Slash Menu",
  "description": "Slash-command palette above the real ClaudePrompt composer — type after / to filter, arrow keys to move.",
  "registryDependencies": [
    "https://brainless.swerdlow.dev/r/claude-prompt.json"
  ],
  "files": [
    {
      "path": "registry/brainless/claude/claude-slash-menu.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { ClaudePrompt } from \"@/registry/brainless/claude/claude-prompt\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * ClaudeSlashMenu — Claude Code's slash-command palette.\n *\n * The command list sits above the real ClaudePrompt composer. Typing after\n * `/` in that input filters by command-name prefix; arrow keys move the\n * active option. Active rows are light blue; inactive rows are gray. Both\n * keep the same fixed-width name column so selection never shifts text.\n */\nexport type SlashCommand = { name: string; description: string };\n\nconst DEFAULT: SlashCommand[] = [\n  { name: \"/agents\", description: \"Manage subagents for specialized tasks\" },\n  { name: \"/clear\", description: \"Clear conversation history and free up context\" },\n  { name: \"/compact\", description: \"Summarize the conversation to save context\" },\n  { name: \"/init\", description: \"Initialize a CLAUDE.md with codebase docs\" },\n  { name: \"/model\", description: \"Change the model for this session\" },\n  { name: \"/review\", description: \"Review a pull request\" },\n];\n\nconst ACTIVE = \"#afd7ff\"; // 38;5;153\nconst INACTIVE = \"#949494\"; // 38;5;246\nconst NAME_COLS = 37; // matches Claude Code's padded name column\n\nexport function ClaudeSlashMenu({\n  commands = DEFAULT,\n  className,\n}: {\n  commands?: SlashCommand[];\n  className?: string;\n}) {\n  const [value, setValue] = React.useState(\"/\");\n  const [active, setActive] = React.useState(0);\n\n  const query = value.startsWith(\"/\") ? value.slice(1) : value;\n  const list = commands.filter((c) =>\n    c.name.slice(1).toLowerCase().startsWith(query.toLowerCase()),\n  );\n  const clampedActive = list.length\n    ? Math.min(active, list.length - 1)\n    : 0;\n\n  function onKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {\n    if (!list.length) return;\n    if (e.key === \"ArrowDown\") {\n      e.preventDefault();\n      setActive((a) => (a + 1) % list.length);\n    } else if (e.key === \"ArrowUp\") {\n      e.preventDefault();\n      setActive((a) => (a - 1 + list.length) % list.length);\n    }\n  }\n\n  return (\n    <div className={cn(\"font-mono text-[13px] leading-[1.6]\", className)}>\n      <ul\n        role=\"listbox\"\n        aria-label=\"Slash commands\"\n        aria-activedescendant={\n          list.length ? `slash-${clampedActive}` : undefined\n        }\n        className=\"mb-2 space-y-0.5\"\n      >\n        {list.map((c, i) => {\n          const activeRow = i === clampedActive;\n          return (\n            <li\n              key={c.name}\n              id={`slash-${i}`}\n              role=\"option\"\n              aria-selected={activeRow}\n              onMouseEnter={() => setActive(i)}\n              className=\"cursor-pointer truncate px-1 py-0.5\"\n              style={{ color: activeRow ? ACTIVE : INACTIVE }}\n            >\n              <span\n                className=\"inline-block\"\n                style={{ width: `${NAME_COLS}ch` }}\n              >\n                {c.name}\n              </span>\n              {c.description}\n            </li>\n          );\n        })}\n      </ul>\n\n      <ClaudePrompt\n        value={value}\n        onChange={(e) => {\n          setValue(e.target.value);\n          setActive(0);\n        }}\n        onKeyDown={onKeyDown}\n        mode=\"auto\"\n      />\n    </div>\n  );\n}\n",
      "type": "registry:ui",
      "target": "components/brainless/claude/claude-slash-menu.tsx"
    }
  ],
  "type": "registry:ui"
}