{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "codex-slash-menu",
  "title": "Codex Slash Menu",
  "description": "Slash-command palette under the real CodexPrompt composer — type after / to filter, arrow keys to move.",
  "registryDependencies": [
    "https://brainless.swerdlow.dev/r/codex-prompt.json"
  ],
  "files": [
    {
      "path": "registry/brainless/codex/codex-slash-menu.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { CodexPrompt } from \"@/registry/brainless/codex/codex-prompt\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * CodexSlashMenu — Codex CLI's slash-command palette.\n *\n * Flat list under the `›` composer: padded command name + description.\n * Type after `/` to filter; arrow keys move the active row.\n */\nexport type CodexSlashCommand = { name: string; description: string };\n\nconst DEFAULT: CodexSlashCommand[] = [\n  { name: \"/model\", description: \"choose what model and reasoning effort to use\" },\n  { name: \"/permissions\", description: \"choose what Codex is allowed to do\" },\n  { name: \"/diff\", description: \"show the unified diff for this session\" },\n  { name: \"/review\", description: \"review a pull request or local changes\" },\n  { name: \"/status\", description: \"show model, limits, and session info\" },\n  { name: \"/compact\", description: \"summarize the conversation to save context\" },\n];\n\nconst ACTIVE = \"#ededed\";\nconst INACTIVE = \"#7a7a7a\";\nconst NAME_COLS = 16;\n\nexport function CodexSlashMenu({\n  commands = DEFAULT,\n  className,\n}: {\n  commands?: CodexSlashCommand[];\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 ? Math.min(active, list.length - 1) : 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      <CodexPrompt\n        value={value}\n        onChange={(e) => {\n          setValue(e.target.value);\n          setActive(0);\n        }}\n        onKeyDown={onKeyDown}\n        placeholder=\"\"\n        mode=\"default\"\n      />\n\n      <ul\n        role=\"listbox\"\n        aria-label=\"Slash commands\"\n        aria-activedescendant={\n          list.length ? `codex-slash-${clampedActive}` : undefined\n        }\n        className=\"mt-2 space-y-0.5 pl-[2ch]\"\n      >\n        {list.map((c, i) => {\n          const activeRow = i === clampedActive;\n          return (\n            <li\n              key={c.name}\n              id={`codex-slash-${i}`}\n              role=\"option\"\n              aria-selected={activeRow}\n              onMouseEnter={() => setActive(i)}\n              className=\"cursor-pointer truncate\"\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    </div>\n  );\n}\n",
      "type": "registry:ui",
      "target": "components/brainless/codex/codex-slash-menu.tsx"
    }
  ],
  "type": "registry:ui"
}