"use client"; import { useState, type ReactNode } from "react"; import { motion, useReducedMotion, type PanInfo } from "motion/react"; type InfiniteStackProps = { /** One entry per card. Needs at least 2. */ items: ReactNode[]; className?: string; /** How many cards show behind the top one. */ visible?: number; /** Name read by screen readers. */ label?: string; }; /* InfiniteStack: swipe or press the arrow keys to send the top card to the back. The stack never ends. */ export function InfiniteStack({ items, className = "rounded-2xl border border-white/10 bg-[#1b1830] p-6 text-white", visible = 3, label = "Card stack", }: InfiniteStackProps) { const reduce = useReducedMotion(); const [order, setOrder] = useState(() => items.map((_, i) => i)); const n = items.length; const next = () => setOrder((o) => [...o.slice(1), o[0]]); const prev = () => setOrder((o) => [o[n - 1], ...o.slice(0, -1)]); const onDragEnd = (_: unknown, info: PanInfo) => { if (Math.abs(info.offset.x) > 80 || Math.abs(info.velocity.x) > 400) next(); }; return (
Card {order[0] + 1} of {n}