{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "avatar-stack",
  "title": "Avatar Stack",
  "description": "Layered portraits with grayscale-to-color hover, spring lift, and a glass +N counter.",
  "dependencies": [
    "framer-motion"
  ],
  "files": [
    {
      "path": "components/trust/AvatarStack.tsx",
      "content": "'use client';\n\nimport { motion } from 'framer-motion';\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n//\n// avatars       Portrait entries — image src, alt, optional name\n// maxVisible    How many faces show before the +N counter\n// label         Optional caption under the stack (e.g. \"Trusted by 2.4k teams\")\n// size          Avatar diameter: sm | md | lg\n// showNames     Reveal names on hover\n// className     Styles for the outer shell\n//\ntype Avatar = {\n  src: string;\n  alt?: string;\n  name?: string;\n};\n\ntype AvatarStackProps = {\n  avatars?: Avatar[];\n  maxVisible?: number;\n  label?: string;\n  size?: 'sm' | 'md' | 'lg';\n  showNames?: boolean;\n  className?: string;\n};\n\nconst DEFAULT_AVATARS: Avatar[] = [\n  {\n    src: 'https://assets.uniquel.io/components/stock/photo-1494790108377-be9c29b29330.jpg',\n    alt: 'Maya Chen',\n    name: 'Maya Chen',\n  },\n  {\n    src: 'https://assets.uniquel.io/components/stock/photo-1507003211169-0a1dd7228f2d.jpg',\n    alt: 'James Okonkwo',\n    name: 'James Okonkwo',\n  },\n  {\n    src: 'https://assets.uniquel.io/components/stock/photo-1438761681033-6461ffad8d80.jpg',\n    alt: 'Sofia Reyes',\n    name: 'Sofia Reyes',\n  },\n  {\n    src: 'https://assets.uniquel.io/components/stock/photo-1472099645785-5658abf4ff4e.jpg',\n    alt: 'Noah Berg',\n    name: 'Noah Berg',\n  },\n  {\n    src: 'https://assets.uniquel.io/components/stock/photo-1544005313-94ddf0286df2.jpg',\n    alt: 'Aria Patel',\n    name: 'Aria Patel',\n  },\n  {\n    src: 'https://assets.uniquel.io/components/stock/photo-1500648767791-00dcc994a43e.jpg',\n    alt: 'Liam Frost',\n    name: 'Liam Frost',\n  },\n];\n\nconst SIZE_MAP = {\n  sm: { px: 28, ring: 2, overlap: -10, text: 'text-[10px]' },\n  md: { px: 36, ring: 2, overlap: -12, text: 'text-xs' },\n  lg: { px: 44, ring: 3, overlap: -14, text: 'text-sm' },\n};\n\nexport default function AvatarStack({\n  avatars = DEFAULT_AVATARS,\n  maxVisible = 4,\n  label = 'Joined by 2.4k builders',\n  size = 'md',\n  showNames = true,\n  className = '',\n}: AvatarStackProps) {\n  const deck = avatars.length ? avatars : DEFAULT_AVATARS;\n  const visible = deck.slice(0, maxVisible);\n  const overflow = Math.max(0, deck.length - maxVisible);\n  const s = SIZE_MAP[size];\n\n  return (\n    <div\n      className={['inline-flex flex-col items-start gap-2.5', className]\n        .filter(Boolean)\n        .join(' ')}\n    >\n      <div className='flex items-center'>\n        {visible.map((avatar, index) => (\n          <motion.div\n            key={`${avatar.src}-${index}`}\n            className='group relative'\n            style={{\n              marginLeft: index === 0 ? 0 : s.overlap,\n              zIndex: index + 1,\n            }}\n            initial={{ opacity: 0, y: 8 }}\n            animate={{ opacity: 1, y: 0 }}\n            transition={{\n              duration: 0.45,\n              delay: index * 0.06,\n              ease: [0.22, 1, 0.36, 1],\n            }}\n            whileHover={{\n              y: -4,\n              zIndex: 20,\n              transition: { type: 'spring', stiffness: 400, damping: 22 },\n            }}\n          >\n            <div\n              className='overflow-hidden rounded-full bg-white shadow-[0_1px_2px_rgba(0,0,0,0.08),0_4px_12px_rgba(0,0,0,0.06)]'\n              style={{\n                width: s.px,\n                height: s.px,\n                outline: `${s.ring}px solid white`,\n              }}\n            >\n              <img\n                src={avatar.src}\n                alt={avatar.alt ?? avatar.name ?? ''}\n                className='h-full w-full object-cover grayscale transition-[filter,transform] duration-500 group-hover:scale-105 group-hover:grayscale-0'\n              />\n            </div>\n            {showNames && avatar.name ? (\n              <span className='pointer-events-none absolute -bottom-7 left-1/2 z-30 -translate-x-1/2 whitespace-nowrap rounded-full bg-gray-900/90 px-2 py-0.5 text-[10px] font-medium tracking-wide text-white opacity-0 shadow-lg backdrop-blur-xs transition-opacity duration-200 group-hover:opacity-100'>\n                {avatar.name}\n              </span>\n            ) : null}\n          </motion.div>\n        ))}\n\n        {overflow > 0 ? (\n          <motion.div\n            className='relative flex items-center justify-center rounded-full border border-white/60 bg-white/70 font-medium tracking-wide text-gray-700 shadow-[0_1px_2px_rgba(0,0,0,0.06)] backdrop-blur-md'\n            style={{\n              width: s.px,\n              height: s.px,\n              marginLeft: s.overlap,\n              zIndex: visible.length + 1,\n              fontSize: size === 'sm' ? 10 : size === 'md' ? 11 : 12,\n            }}\n            initial={{ opacity: 0, scale: 0.85 }}\n            animate={{ opacity: 1, scale: 1 }}\n            transition={{\n              duration: 0.4,\n              delay: visible.length * 0.06,\n              ease: [0.22, 1, 0.36, 1],\n            }}\n            whileHover={{\n              y: -3,\n              transition: { type: 'spring', stiffness: 400, damping: 22 },\n            }}\n          >\n            +{overflow}\n          </motion.div>\n        ) : null}\n      </div>\n\n      {label ? (\n        <motion.p\n          className={['font-medium tracking-wide text-gray-500', s.text].join(\n            ' '\n          )}\n          initial={{ opacity: 0 }}\n          animate={{ opacity: 1 }}\n          transition={{ duration: 0.5, delay: 0.35 }}\n        >\n          {label}\n        </motion.p>\n      ) : null}\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "@components/trust/AvatarStack.tsx"
    }
  ],
  "categories": [
    "trust"
  ],
  "type": "registry:component"
}