{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "card-stack", "title": "Card Stack", "description": "A stacked card fan animation.", "dependencies": [ "motion" ], "files": [ { "path": "registry/new-york/components/card-stack/card-stack.tsx", "type": "registry:component", "content": "\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { motion, type Variants } from \"motion/react\";\nimport Image from \"next/image\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface CardItem {\n id: string | number;\n name: string;\n image: string;\n position: { x: number; y: number; rotate: number };\n}\n\nexport const cryptoCards: CardItem[] = [\n {\n id: 1,\n name: \"USDT\",\n image: \"https://assets.coingecko.com/coins/images/325/large/Tether.png\",\n position: { x: -300, y: 12, rotate: -10 },\n },\n {\n id: 2,\n name: \"BNB\",\n image:\n \"https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png\",\n position: { x: -180, y: -20, rotate: -6 },\n },\n {\n id: 3,\n name: \"USDC\",\n image: \"https://assets.coingecko.com/coins/images/6319/large/usdc.png\",\n position: { x: -60, y: 0, rotate: -2 },\n },\n {\n id: 4,\n name: \"Solana\",\n image: \"https://assets.coingecko.com/coins/images/4128/large/solana.png\",\n position: { x: 60, y: 0, rotate: 2 },\n },\n {\n id: 5,\n name: \"Ethereum\",\n image: \"https://assets.coingecko.com/coins/images/279/large/ethereum.png\",\n position: { x: 180, y: 4, rotate: 6 },\n },\n {\n id: 6,\n name: \"Bitcoin\",\n image: \"https://assets.coingecko.com/coins/images/1/large/bitcoin.png\",\n position: { x: 300, y: -5, rotate: 10 },\n },\n];\n\n// Hoisted so these aren't reallocated on every render/every card\nconst CARD_VARIANTS: Variants = {\n hidden: { x: 30, y: 100, rotate: -30, scale: 0.6, opacity: 0 },\n stacked: { x: 0, y: 0, rotate: 0, scale: 1, opacity: 1 },\n fanned: ({ x, y, rotate }: { x: number; y: number; rotate: number }) => ({\n x,\n y,\n rotate,\n scale: 1,\n opacity: 1,\n }),\n};\n\nexport interface CardStackProps {\n items?: CardItem[];\n openDelay?: number;\n settleDelay?: number;\n hoverOffset?: number;\n className?: string;\n cardClassName?: string;\n}\n\nexport default function CardStack({\n items = cryptoCards,\n openDelay = 600,\n settleDelay = 500,\n hoverOffset = -20,\n className,\n cardClassName,\n}: CardStackProps) {\n const [open, setOpen] = useState(false);\n const [isLoaded, setIsLoaded] = useState(false);\n\n useEffect(() => {\n let settleTimer: ReturnType;\n const openTimer = setTimeout(() => {\n setOpen(true);\n settleTimer = setTimeout(() => setIsLoaded(true), settleDelay);\n }, openDelay);\n\n return () => {\n clearTimeout(openTimer);\n clearTimeout(settleTimer);\n };\n }, [openDelay, settleDelay]);\n\n return (\n \n {items.map((card, index) => (\n \n \n \n ))}\n \n );\n}\n" } ], "type": "registry:component" }