{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "kbd-glass",
  "title": "Glass kbd",
  "description": "Styled kbd: the Glass set. 5 decorative kbd variations (FrostKbd, TintKbd, SmokeKbd, CrystalKbd, DepthKbd) 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",
    "@ai2/glass"
  ],
  "files": [
    {
      "path": "registry/ai2/styled/kbd-glass.tsx",
      "content": "\"use client\"\n\nimport type * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { glassDepth } from \"@/registry/ai2/ui/glass\"\n\n/* Glass kbd family: 5 frosted/semi-transparent keycaps. Color comes ONLY from tokens\n   (via an alpha utility or color-mix). Static - needs no motion. The surface derives\n   from glassDepth in @ai2/glass (AGENTS.md 4.5). Together with the badges, keycaps\n   are the smallest glass surfaces in the system (h-5..h-8). There is next to no\n   content behind a keycap to diffuse, so the scale sits at the very bottom end: sm\n   carries the body, md appears only on the two variations where diffusing makes\n   sense (Smoke, Depth). lg/xl are NEVER used. */\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 base =\n  \"inline-flex w-fit shrink-0 select-none items-center justify-center gap-1 whitespace-nowrap rounded-md border font-mono font-medium leading-none [&_svg]:size-3 [&_svg]:shrink-0 [&_i]:text-xs [&_i]:leading-none\"\n\ntype Props = React.ComponentProps<\"kbd\"> & { size?: StyledSize }\n\n/* Frost: a plain frosted-glass cap. Depth = sm (4px). The lightest step is the default for a keycap: in a 24px box the \"glass\" feel comes not from the blur but from the library signature's inner top highlight - which is exactly what a keycap wants (light breaking at the top edge). */\nexport function FrostKbd({ className, size = \"md\", children, ...props }: Props) {\n  return (\n    <kbd\n      data-slot=\"styled-kbd\"\n      className={cn(\n        base,\n        box[size],\n        glassDepth.sm,\n        \"border-border/60 text-foreground\",\n        className\n      )}\n      {...props}\n    >\n      {children ?? \"Ctrl\"}\n    </kbd>\n  )\n}\n\n/* Tint: an info-toned semi-transparent glass cap. Depth = sm (4px): what carries the colour is the surface, not the blur; more blur piles the hue onto itself and muddies it. info was chosen as the tone: primary sits on the neutral ramp, so a \"tint\" would stay colourless and look identical to Smoke; info carries a real colour. */\nexport function TintKbd({ className, size = \"md\", children, ...props }: Props) {\n  return (\n    <kbd\n      data-slot=\"styled-kbd\"\n      data-tone=\"info\"\n      className={cn(\n        base,\n        box[size],\n        glassDepth.sm,\n        \"border-info/30 bg-info/15 text-info supports-[backdrop-filter]:bg-info/15\",\n        className\n      )}\n      {...props}\n    >\n      {children ?? \"Ctrl\"}\n    </kbd>\n  )\n}\n\n/* Smoke: a neutral cap darkened with foreground. Depth = md (8px). Smoke means diffusion, so it sits one step above Frost/Crystal/Tint; but on a keycap this is also the ceiling. What separates it from Tint is the absence of hue. */\nexport function SmokeKbd({ className, size = \"md\", children, ...props }: Props) {\n  return (\n    <kbd\n      data-slot=\"styled-kbd\"\n      className={cn(\n        base,\n        box[size],\n        glassDepth.md,\n        \"border-foreground/10 bg-foreground/15 text-foreground supports-[backdrop-filter]:bg-foreground/15\",\n        className\n      )}\n      {...props}\n    >\n      {children ?? \"Ctrl\"}\n    </kbd>\n  )\n}\n\n/* Crystal: clear glass. Depth = sm (4px), the least diffusing in the family - the\n   condition for being \"clear\" is being able to see what is behind. It used to draw\n   the top/bottom inset lines by hand; the lib signature already does exactly that,\n   and writing a second inset on top of it would have deleted the signature through\n   twMerge. */\nexport function CrystalKbd({ className, size = \"md\", children, ...props }: Props) {\n  return (\n    <kbd\n      data-slot=\"styled-kbd\"\n      className={cn(\n        base,\n        box[size],\n        glassDepth.sm,\n        \"border-[color-mix(in_oklab,var(--color-foreground)_20%,transparent)] text-foreground\",\n        className\n      )}\n      {...props}\n    >\n      {children ?? \"Ctrl\"}\n    </kbd>\n  )\n}\n\n/* Depth: a glass body + a cast shadow, so the lid looks lifted off the surface.\n   Depth = md (8px), the deepest step in this file: this is the only surface that\n   rises, and a gap that genuinely needs diffusing forms underneath it. It does not\n   go up to lg - there is nothing for a 16px blur to show on a lid this size.\n   The shadow is now a drop-shadow (the filter group). The constraint the old note\n   identified still holds - box-shadow is a single twMerge group and shadow-lg would\n   silently delete the lib signature - but there is a solution now: drop-shadow is a\n   completely different CSS property, so Depth gets both the rising shadow and the\n   ai2 signature's top highlight.\n   The neutral black utility is deliberate: a foreground-based color-mix shadow\n   would turn into a WHITE halo in the dark theme (reading as a glow, not a\n   shadow). */\nexport function DepthKbd({ className, size = \"md\", children, ...props }: Props) {\n  return (\n    <kbd\n      data-slot=\"styled-kbd\"\n      className={cn(\n        base,\n        box[size],\n        glassDepth.md,\n        \"border-border/60 text-foreground drop-shadow-md\",\n        className\n      )}\n      {...props}\n    >\n      {children ?? \"Ctrl\"}\n    </kbd>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/ui/kbd-glass.tsx"
    }
  ],
  "categories": [
    "styled",
    "kbd"
  ],
  "type": "registry:component"
}