{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "kbd-combo",
  "title": "Combo kbd",
  "description": "Styled kbd: the Combo set. 5 decorative kbd variations (ComboKbd, ChainKbd, PlusKbd, SequenceKbd, GroupKbd) on the ai2 token system, driven by CSS token transitions and sized sm to xl. Part of the free styled layer.",
  "dependencies": [],
  "registryDependencies": [
    "@ai2/tokens"
  ],
  "files": [
    {
      "path": "registry/ai2/styled/kbd-combo.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* Combo kbd family: multi-key combinations. Every variant carries real <kbd> caps inside a root <kbd>; for accessibility the root holds the sr-only full text (\"Ctrl plus K\") and the visual cap stack is aria-hidden, so a screen reader hears one readable name. Colour comes ONLY from tokens. Static - no motion. */\n\nexport type StyledSize = \"sm\" | \"md\" | \"lg\" | \"xl\"\n\nconst box: Record<StyledSize, string> = {\n  sm: \"h-5 px-1.5 text-xs\",\n  md: \"h-6 px-2 text-xs\",\n  lg: \"h-7 px-2.5 text-sm\",\n  xl: \"h-8 px-3 text-sm\",\n}\n\nconst gap: Record<StyledSize, string> = {\n  sm: \"gap-1\",\n  md: \"gap-1\",\n  lg: \"gap-1.5\",\n  xl: \"gap-1.5\",\n}\n\nconst conn: Record<StyledSize, string> = {\n  sm: \"text-[10px]\",\n  md: \"text-xs\",\n  lg: \"text-xs\",\n  xl: \"text-sm\",\n}\n\nconst rootBase =\n  \"inline-flex w-fit shrink-0 select-none items-center whitespace-nowrap font-mono font-medium leading-none text-foreground\"\n\nconst capBase =\n  \"inline-flex shrink-0 select-none items-center justify-center gap-1 whitespace-nowrap rounded-md border border-border bg-surface-2 font-mono font-medium leading-none text-foreground [&_svg]:size-3 [&_svg]:shrink-0 [&_i]:text-xs [&_i]:leading-none\"\n\ntype Props = React.ComponentProps<\"kbd\"> & {\n  size?: StyledSize\n  /** Cap texts; the variant default is used when none are given. */\n  keys?: string[]\n}\n\n/* Tek kapak. */\nfunction Cap({ size, children }: { size: StyledSize; children: React.ReactNode }) {\n  return <kbd className={cn(capBase, box[size])}>{children}</kbd>\n}\n\n/* The full combination text for screen readers (\"Ctrl plus K\" / \"G then P\"). */\nfunction label(keys: string[], word: string) {\n  return keys.join(` ${word} `)\n}\n\n/* Combo: sade yan yana kapaklar, baglayici yok. */\nexport function ComboKbd({ className, size = \"md\", keys, children, ...props }: Props) {\n  const list = keys ?? [\"Ctrl\", \"K\"]\n  return (\n    <kbd data-slot=\"styled-kbd\" className={cn(rootBase, gap[size], className)} {...props}>\n      {children ?? (\n        <>\n          <span className=\"sr-only\">{label(list, \"plus\")}</span>\n          <span aria-hidden=\"true\" className={cn(\"inline-flex items-center\", gap[size])}>\n            {list.map((k, i) => (\n              <Cap key={`${k}-${i}`} size={size}>\n                {k}\n              </Cap>\n            ))}\n          </span>\n        </>\n      )}\n    </kbd>\n  )\n}\n\n/* Chain: segments joined inside a single shell, divided by separator lines. */\nexport function ChainKbd({ className, size = \"md\", keys, children, ...props }: Props) {\n  const list = keys ?? [\"Ctrl\", \"Shift\", \"P\"]\n  return (\n    <kbd\n      data-slot=\"styled-kbd\"\n      className={cn(\n        rootBase,\n        \"overflow-hidden rounded-md border border-border bg-surface-2\",\n        className\n      )}\n      {...props}\n    >\n      {children ?? (\n        <>\n          <span className=\"sr-only\">{label(list, \"plus\")}</span>\n          <span aria-hidden=\"true\" className=\"inline-flex items-center divide-x divide-border\">\n            {list.map((k, i) => (\n              <kbd\n                key={`${k}-${i}`}\n                className={cn(\n                  \"inline-flex shrink-0 items-center justify-center whitespace-nowrap font-mono font-medium leading-none [&_svg]:size-3 [&_svg]:shrink-0 [&_i]:text-xs [&_i]:leading-none\",\n                  box[size]\n                )}\n              >\n                {k}\n              </kbd>\n            ))}\n          </span>\n        </>\n      )}\n    </kbd>\n  )\n}\n\n/* Plus: kapaklar arasinda gorunur bir \"+\" baglayici. */\nexport function PlusKbd({ className, size = \"md\", keys, children, ...props }: Props) {\n  const list = keys ?? [\"Cmd\", \"S\"]\n  return (\n    <kbd data-slot=\"styled-kbd\" className={cn(rootBase, gap[size], className)} {...props}>\n      {children ?? (\n        <>\n          <span className=\"sr-only\">{label(list, \"plus\")}</span>\n          <span aria-hidden=\"true\" className={cn(\"inline-flex items-center\", gap[size])}>\n            {list.map((k, i) => (\n              <React.Fragment key={`${k}-${i}`}>\n                {i > 0 ? (\n                  <span className={cn(\"text-muted-foreground\", conn[size])}>+</span>\n                ) : null}\n                <Cap size={size}>{k}</Cap>\n              </React.Fragment>\n            ))}\n          </span>\n        </>\n      )}\n    </kbd>\n  )\n}\n\n/* Sequence: once X sonra Y - kapaklar arasinda \"then\" baglayicisi. */\nexport function SequenceKbd({ className, size = \"md\", keys, children, ...props }: Props) {\n  const list = keys ?? [\"G\", \"P\"]\n  return (\n    <kbd data-slot=\"styled-kbd\" className={cn(rootBase, gap[size], className)} {...props}>\n      {children ?? (\n        <>\n          <span className=\"sr-only\">{label(list, \"then\")}</span>\n          <span aria-hidden=\"true\" className={cn(\"inline-flex items-center\", gap[size])}>\n            {list.map((k, i) => (\n              <React.Fragment key={`${k}-${i}`}>\n                {i > 0 ? (\n                  <span className={cn(\"font-sans lowercase text-muted-foreground\", conn[size])}>\n                    then\n                  </span>\n                ) : null}\n                <Cap size={size}>{k}</Cap>\n              </React.Fragment>\n            ))}\n          </span>\n        </>\n      )}\n    </kbd>\n  )\n}\n\n/* Group: kapaklar tek bir cerceveli kap icinde toplanir. */\nexport function GroupKbd({ className, size = \"md\", keys, children, ...props }: Props) {\n  const list = keys ?? [\"Alt\", \"Enter\"]\n  return (\n    <kbd\n      data-slot=\"styled-kbd\"\n      className={cn(\n        rootBase,\n        \"rounded-lg border border-border bg-[color-mix(in_oklab,var(--color-foreground)_4%,transparent)] p-1\",\n        gap[size],\n        className\n      )}\n      {...props}\n    >\n      {children ?? (\n        <>\n          <span className=\"sr-only\">{label(list, \"plus\")}</span>\n          <span aria-hidden=\"true\" className={cn(\"inline-flex items-center\", gap[size])}>\n            {list.map((k, i) => (\n              <Cap key={`${k}-${i}`} size={size}>\n                {k}\n              </Cap>\n            ))}\n          </span>\n        </>\n      )}\n    </kbd>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/ui/kbd-combo.tsx"
    }
  ],
  "categories": [
    "styled",
    "kbd"
  ],
  "type": "registry:component"
}