{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "jarvis-dock",
  "type": "registry:component",
  "title": "Jarvis Dock",
  "description": "Floating bottom dock with quick-action buttons + a command-palette trigger.",
  "dependencies": [
    "@vllnt/ui@^0.2.1"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/default/jarvis-dock/jarvis-dock.tsx",
      "content": "\"use client\";\n\nimport {\n  type ComponentPropsWithoutRef,\n  forwardRef,\n  type ReactNode,\n} from \"react\";\n\nimport { cn } from \"@vllnt/ui\";\n\n/**\n * Tone of a dock action — drives its accent color.\n *\n * @public\n */\nexport type JarvisDockTone = \"danger\" | \"neutral\" | \"primary\" | \"success\";\n\nconst TONE_CLASS: Record<JarvisDockTone, string> = {\n  danger: \"text-red-600 dark:text-red-400\",\n  neutral: \"text-foreground\",\n  primary: \"text-blue-600 dark:text-blue-400\",\n  success: \"text-emerald-600 dark:text-emerald-400\",\n};\n\n/**\n * One action button slotted in the dock.\n *\n * @public\n */\nexport type JarvisDockAction = {\n  /** Optional badge value rendered as a small dot or count. */\n  badge?: ReactNode;\n  /** Glyph rendered above the label (single character or icon). */\n  glyph: ReactNode;\n  /** Stable identifier — used as the React key + analytics hook. */\n  id: string;\n  /** Short label shown beneath the glyph. */\n  label: ReactNode;\n  /** Click handler. */\n  onActivate: () => void;\n  /** Optional tone. Defaults to `\"neutral\"`. */\n  tone?: JarvisDockTone;\n};\n\n/**\n * Localizable strings.\n *\n * @public\n */\nexport type JarvisDockLabels = {\n  /** Aria-label for the command-palette trigger. Defaults to `\"Open command palette\"`. */\n  paletteTrigger?: string;\n  /** Aria-label for the dock. Defaults to `\"Jarvis dock\"`. */\n  region?: string;\n};\n\nconst DEFAULT_LABELS = {\n  paletteTrigger: \"Open command palette\",\n  region: \"Jarvis dock\",\n} as const satisfies Required<JarvisDockLabels>;\n\n/**\n * Props for {@link JarvisDock}.\n *\n * @public\n */\nexport type JarvisDockProps = {\n  /** Action buttons in render order. */\n  actions: JarvisDockAction[];\n  /** Localizable strings. */\n  labels?: JarvisDockLabels;\n  /** Optional handler for the \"...\" command-palette trigger. */\n  onOpenPalette?: () => void;\n} & ComponentPropsWithoutRef<\"nav\">;\n\nconst ActionButton = (props: {\n  action: JarvisDockAction;\n}): React.ReactElement => {\n  const { action } = props;\n  const tone = action.tone ?? \"neutral\";\n  const handleClick = (): void => {\n    action.onActivate();\n  };\n  return (\n    <button\n      className=\"group relative flex size-12 flex-col items-center justify-center gap-0.5 rounded-md border border-transparent text-[10px] uppercase tracking-wide text-muted-foreground transition-colors hover:border-border hover:bg-muted/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n      data-jarvis-action={action.id}\n      data-jarvis-tone={tone}\n      onClick={handleClick}\n      type=\"button\"\n    >\n      <span\n        aria-hidden=\"true\"\n        className={cn(\n          \"text-base leading-none transition-transform group-hover:scale-110\",\n          TONE_CLASS[tone],\n        )}\n      >\n        {action.glyph}\n      </span>\n      <span className=\"truncate\">{action.label}</span>\n      {action.badge ? (\n        <span\n          className=\"absolute right-1 top-1 inline-flex min-h-[14px] min-w-[14px] items-center justify-center rounded-full bg-foreground px-1 text-[9px] font-medium text-background\"\n          data-jarvis-badge\n        >\n          {action.badge}\n        </span>\n      ) : null}\n    </button>\n  );\n};\n\n/**\n * Floating bottom dock for the spatial canvas. Renders a compact row\n * of agent / quick-action buttons plus a trailing command-palette\n * trigger. Pure presentation; the host wires `onActivate` per action\n * and `onOpenPalette` for the palette button.\n *\n * @example\n * ```tsx\n * <JarvisDock\n *   actions={[\n *     { id: \"summon\", glyph: \"+\", label: \"Summon\", tone: \"primary\",\n *       onActivate: () => spawnAgent() },\n *     { id: \"review\", glyph: \"✓\", label: \"Review\", tone: \"success\",\n *       onActivate: () => openReview() },\n *   ]}\n *   onOpenPalette={() => openCommandPalette()}\n * />\n * ```\n *\n * @public\n */\nexport const JarvisDock = forwardRef<HTMLElement, JarvisDockProps>(\n  (props, ref) => {\n    const { actions, className, labels, onOpenPalette, ...rest } = props;\n    const resolvedLabels = { ...DEFAULT_LABELS, ...labels };\n    const handlePalette = (): void => {\n      onOpenPalette?.();\n    };\n    return (\n      <nav\n        aria-label={resolvedLabels.region}\n        className={cn(\n          \"inline-flex items-center gap-1 rounded-2xl border bg-background/90 p-1.5 shadow-md backdrop-blur\",\n          className,\n        )}\n        data-jarvis-dock\n        ref={ref}\n        {...rest}\n      >\n        {actions.map((action) => (\n          <ActionButton action={action} key={action.id} />\n        ))}\n        {onOpenPalette ? (\n          <>\n            <span aria-hidden=\"true\" className=\"mx-1 h-8 w-px bg-border\" />\n            <button\n              aria-label={resolvedLabels.paletteTrigger}\n              className=\"flex size-12 items-center justify-center rounded-md border border-transparent text-base text-muted-foreground transition-colors hover:border-border hover:bg-muted/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n              data-jarvis-palette-trigger\n              onClick={handlePalette}\n              type=\"button\"\n            >\n              <span aria-hidden=\"true\">⌘</span>\n            </button>\n          </>\n        ) : null}\n      </nav>\n    );\n  },\n);\nJarvisDock.displayName = \"JarvisDock\";\n",
      "type": "registry:component"
    }
  ],
  "version": "0.2.1",
  "stability": "stable"
}
