{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "kbd",
  "title": "Kbd",
  "description": "A keyboard chord rendered with the right glyphs for the reader's platform.",
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/default/kbd/kbd.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport type KbdProps = Omit<React.HTMLAttributes<HTMLElement>, \"children\"> & {\n  /** A chord such as \"Mod+K\", or the keys already split apart. */\n  keys: string | readonly string[]\n  /** Overrides platform detection. */\n  platform?: \"auto\" | \"mac\" | \"other\"\n  separator?: React.ReactNode\n}\n\nconst macNames: Record<string, string> = {\n  mod: \"⌘\",\n  meta: \"⌘\",\n  cmd: \"⌘\",\n  command: \"⌘\",\n  alt: \"⌥\",\n  option: \"⌥\",\n  shift: \"⇧\",\n  ctrl: \"⌃\",\n  control: \"⌃\",\n  enter: \"↵\",\n  backspace: \"⌫\",\n  escape: \"Esc\",\n  esc: \"Esc\",\n  up: \"↑\",\n  down: \"↓\",\n  left: \"←\",\n  right: \"→\",\n}\n\nconst otherNames: Record<string, string> = {\n  mod: \"Ctrl\",\n  meta: \"Win\",\n  cmd: \"Ctrl\",\n  command: \"Ctrl\",\n  alt: \"Alt\",\n  option: \"Alt\",\n  shift: \"Shift\",\n  ctrl: \"Ctrl\",\n  control: \"Ctrl\",\n  enter: \"Enter\",\n  backspace: \"Backspace\",\n  escape: \"Esc\",\n  esc: \"Esc\",\n  up: \"↑\",\n  down: \"↓\",\n  left: \"←\",\n  right: \"→\",\n}\n\n/** Spoken form, so a screen reader says \"Command\" rather than the glyph. */\nconst spoken: Record<string, string> = {\n  \"⌘\": \"Command\",\n  \"⌥\": \"Option\",\n  \"⇧\": \"Shift\",\n  \"⌃\": \"Control\",\n  \"↵\": \"Enter\",\n  \"⌫\": \"Backspace\",\n  \"↑\": \"Up arrow\",\n  \"↓\": \"Down arrow\",\n  \"←\": \"Left arrow\",\n  \"→\": \"Right arrow\",\n}\n\nconst noop = () => () => {}\n\nfunction isMacClient() {\n  return /mac|iphone|ipad|ipod/i.test(navigator.platform || navigator.userAgent)\n}\n\nexport function Kbd({\n  keys,\n  platform = \"auto\",\n  separator,\n  className,\n  ...rootProps\n}: KbdProps) {\n  // The server cannot know the platform, so it renders the portable names and\n  // the client swaps in the Mac glyphs once it knows better.\n  const detected = React.useSyncExternalStore(noop, isMacClient, () => false)\n\n  const mac = platform === \"auto\" ? detected : platform === \"mac\"\n  const names = mac ? macNames : otherNames\n\n  const parts = (\n    typeof keys === \"string\" ? keys.split(\"+\").map((key) => key.trim()) : keys\n  ).filter(Boolean)\n\n  const rendered = parts.map(\n    (key) =>\n      names[key.toLowerCase()] ?? (key.length === 1 ? key.toUpperCase() : key)\n  )\n\n  return (\n    <span\n      data-slot=\"kbd\"\n      className={cn(\"inline-flex items-center gap-0.5 align-middle\", className)}\n      {...rootProps}\n    >\n      <span className=\"sr-only\">\n        {rendered.map((key) => spoken[key] ?? key).join(\" plus \")}\n      </span>\n\n      {rendered.map((key, index) => (\n        <React.Fragment key={`${key}-${index}`}>\n          {index > 0 && separator ? (\n            <span\n              aria-hidden=\"true\"\n              className=\"text-muted-foreground text-[0.6875rem]\"\n            >\n              {separator}\n            </span>\n          ) : null}\n          <kbd\n            aria-hidden=\"true\"\n            className=\"border-border bg-muted text-muted-foreground inline-flex min-w-[1.5rem] items-center justify-center rounded border px-1.5 py-0.5 font-[family-name:var(--font-mono),monospace] text-[0.6875rem] leading-none\"\n          >\n            {key}\n          </kbd>\n        </React.Fragment>\n      ))}\n    </span>\n  )\n}\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "docs",
    "keyboard",
    "hint"
  ],
  "type": "registry:ui"
}