{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "avatars-glass",
  "title": "Glass avatars",
  "description": "Styled avatars: the Glass set. 5 decorative avatars variations (FrostAvatar, TintAvatar, SheenAvatar, CrystalAvatar, HaloGlassAvatar) 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/avatars-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 avatar family: 5 decorative avatars on a frosted/translucent theme.\n   Initial-based (no external image) - a consumer can put an <img> in place of\n   the initials. Color comes ONLY from tokens (transparency via color-mix), size\n   = the box scale. The sheen sweep is pure CSS and is disabled under\n   reduced-motion (motion-reduce).\n\n   The surface derives from glassDepth in @ai2/glass (AGENTS.md 4.5).\n   What is special about this family: what sits \"behind\" the glass overlay is not\n   the page but the avatar's OWN opaque face (the initials). So the blur is not\n   diffusing content here, it is diffusing a single pair of letters - and in a\n   32px circle a 16px blur erases the letters completely. That is why the scale\n   is shifted down: sm carries the body, md is used only on HaloGlass, the\n   largest surface, and on the default Frost. lg/xl are not used. */\n\nexport type StyledSize = \"sm\" | \"md\" | \"lg\" | \"xl\"\n\nconst box: Record<StyledSize, string> = {\n  sm: \"size-8 text-xs\",\n  md: \"size-10 text-sm\",\n  lg: \"size-12 text-base\",\n  xl: \"size-16 text-lg\",\n}\n\nconst face =\n  \"flex size-full items-center justify-center rounded-full bg-secondary font-medium text-secondary-foreground select-none\"\n\ntype Props = React.ComponentProps<\"div\"> & { size?: StyledSize; initials?: string }\n\n/* Frost: a frosted-glass overlay. Depth = md (8px), the canonical default: the initials stay readable but sit behind the frost - the \"normal\" state of this family. */\nexport function FrostAvatar({ className, size = \"md\", initials = \"AI\", ...props }: Props) {\n  return (\n    <div data-slot=\"styled-avatar\" className={cn(\"relative inline-flex\", box[size], className)} {...props}>\n      <span className={face}>{initials}</span>\n      <span\n        aria-hidden=\"true\"\n        className={cn(\n          glassDepth.md,\n          \"pointer-events-none absolute inset-0 rounded-full border border-surface-3\"\n        )}\n      />\n    </div>\n  )\n}\n\n/* Tint: an info-toned transparent overlay. Depth = sm (4px): the initials still have to be readable behind the tint, and what carries the colour is the surface itself rather than the blur. The tone is info: primary/brand sits on the neutral ramp, so it would be an invisible tint. */\nexport function TintAvatar({ className, size = \"md\", initials = \"AI\", ...props }: Props) {\n  return (\n    <div data-slot=\"styled-avatar\" className={cn(\"relative inline-flex\", box[size], className)} {...props}>\n      <span className={face}>{initials}</span>\n      <span\n        aria-hidden=\"true\"\n        className={cn(\n          glassDepth.sm,\n          \"pointer-events-none absolute inset-0 rounded-full border border-info/30\",\n          \"bg-[color-mix(in_oklab,var(--color-info)_20%,transparent)] supports-[backdrop-filter]:bg-[color-mix(in_oklab,var(--color-info)_20%,transparent)]\"\n        )}\n      />\n    </div>\n  )\n}\n\n/* Sheen: a single token light sweep passing over it on hover. Depth = sm (4px): what this variation is about is the motion, not the glass - the more the blur grows, the more the sweep becomes a blurred smudge. bg was also pulled from the library's /50 to /25: the glass overlay sits above the sheen in the DOM and /50 was swallowing the sweep. The blur and the signature come from the library, only the surface opacity is tuned for this composition. */\nexport function SheenAvatar({ className, size = \"md\", initials = \"AI\", ...props }: Props) {\n  return (\n    <div\n      data-slot=\"styled-avatar\"\n      className={cn(\"group relative inline-flex overflow-hidden rounded-full\", box[size], className)}\n      {...props}\n    >\n      <span className={face}>{initials}</span>\n      <span\n        aria-hidden=\"true\"\n        className=\"pointer-events-none absolute inset-y-0 -left-full w-2/3 -skew-x-12 bg-gradient-to-r from-transparent via-foreground/20 to-transparent transition-[left] duration-700 ease-out group-hover:left-full motion-reduce:hidden\"\n      />\n      <span\n        aria-hidden=\"true\"\n        className={cn(\n          glassDepth.sm,\n          \"pointer-events-none absolute inset-0 rounded-full border border-surface-3\",\n          \"bg-background/25 supports-[backdrop-filter]:bg-background/25\"\n        )}\n      />\n    </div>\n  )\n}\n\n/* Crystal: clear glass. Depth = sm (4px), the least diffusing in the family - the\n   initials read most clearly here, which is the condition for being \"clear\". It\n   used to draw its own top/bottom inset lines by hand; the lib signature already\n   does exactly that, and writing a second inset on top of it would have deleted the\n   signature through twMerge. */\nexport function CrystalAvatar({ className, size = \"md\", initials = \"AI\", ...props }: Props) {\n  return (\n    <div data-slot=\"styled-avatar\" className={cn(\"relative inline-flex\", box[size], className)} {...props}>\n      <span className={face}>{initials}</span>\n      <span\n        aria-hidden=\"true\"\n        className={cn(\n          glassDepth.sm,\n          \"pointer-events-none absolute inset-0 rounded-full\",\n          \"border border-[color-mix(in_oklab,var(--color-foreground)_20%,transparent)]\"\n        )}\n      />\n    </div>\n  )\n}\n\n/* HaloGlass: a transparent glass halo ring (an outer offset ring). Depth = md (8px). This is the LARGEST surface in the file (it extends outside the avatar with -inset-1.5) and the only true glass with the page behind it: the others have the avatar's own opaque face behind them, while this ring sits over the page. Because it is the one variation where the blur really does a job, it sits a step higher. */\nexport function HaloGlassAvatar({ className, size = \"md\", initials = \"AI\", ...props }: Props) {\n  return (\n    <div data-slot=\"styled-avatar\" className={cn(\"relative inline-flex\", box[size], className)} {...props}>\n      <span\n        aria-hidden=\"true\"\n        className={cn(\n          glassDepth.md,\n          \"pointer-events-none absolute -inset-1.5 rounded-full border border-surface-3\"\n        )}\n      />\n      <span className={cn(face, \"relative border border-surface-3\")}>{initials}</span>\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/ui/avatars-glass.tsx"
    }
  ],
  "categories": [
    "styled",
    "avatars"
  ],
  "type": "registry:component"
}