Card Swap
godui/card-swapFreeComponent
A 3D stack of cards that cycles through a showcase loop, with pointer parallax and spring re-flow.
Install it
npx shadcn@latest add https://godui.design/r/card-swap.jsonSource
1"use client";23import { motion, useReducedMotion } from "framer-motion";4import * as React from "react";56export type CardSwapProps = Omit<7 React.HTMLAttributes<HTMLDivElement>,8 "children"9> & {10 /** Cards to cycle through, front to back. Provide 2–5. */11 children?: React.ReactNode;12 /** Auto-advance interval in ms. Set `0` to disable. */13 interval?: number;14 /** Pause the auto-advance while the pointer is over the stack. */15 pauseOnHover?: boolean;16 /** Vertical offset (px) between stacked cards. */17 offsetY?: number;18 /** Horizontal offset (px) between stacked cards. */19 offsetX?: number;20 /** Scale step removed per card going back. */21 scaleStep?: number;22};2324const CardSwap = React.forwardRef<HTMLDivElement, CardSwapProps>(25 (26 {27 children,28 interval = 3500,29 pauseOnHover = true,30 offsetY = 28,31 offsetX = 22,32 scaleStep = 0.06,33 className,34 onPointerMove,35 onPointerLeave,36 ...props37 },38 forwardedRef,39 ) => {40 const ref = React.useRef<HTMLDivElement>(null);41 React.useImperativeHandle(42 forwardedRef,43 () => ref.current as HTMLDivElement,44 );45 const reduce = useReducedMotion();46 const items = React.Children.toArray(children);47 const n = items.length;4849 // `order[r]` is the item index sitting at rank `r` (0 = front).50 const [order, setOrder] = React.useState(() =>51 Array.from({ length: n }, (_, i) => i),52 );53 React.useEffect(() => {54 setOrder(Array.from({ length: n }, (_, i) => i));55 }, [n]);5657 const [tilt, setTilt] = React.useState({ x: 0, y: 0 });58 const [paused, setPaused] = React.useState(false);5960 const advance = React.useCallback(() => {61 setOrder((o) => (o.length ? [...o.slice(1), o[0] as number] : o));62 }, []);63 const retreat = React.useCallback(() => {64 setOrder((o) =>65 o.length ? [o[o.length - 1] as number, ...o.slice(0, -1)] : o,66 );67 }, []);6869 React.useEffect(() => {70 if (!interval || paused || n < 2) return;71 const t = setInterval(advance, interval);72 return () => clearInterval(t);73 }, [interval, paused, n, advance]);7475 const handleMove = (e: React.PointerEvent<HTMLDivElement>) => {76 onPointerMove?.(e);77 if (reduce) return;78 const el = ref.current;79 if (!el) return;80 const rect = el.getBoundingClientRect();81 const px = (e.clientX - rect.left) / rect.width - 0.5;82 const py = (e.clientY - rect.top) / rect.height - 0.5;83// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from godui
All 105 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | godui | Components | Free | 1 dep | |
| Agent Flowagent-flow | godui | Components | Free | 1 dep | |
| Agent Timelineagent-timeline | godui | Components | Free | 1 dep | |
| Animated Beamanimated-beam | godui | Components | Free | 1 dep | |
| Animated Testimonialsanimated-testimonials | godui | Components | Free | 1 dep | |
| Animated Tooltipanimated-tooltip | godui | Components | Free | 1 dep | |
| App Showcaseapp-showcase | godui | Components | Free | 1 dep | |
| Aurora Textaurora-text | godui | Components | Free | no deps |
