react-cards-pro
v1.6.1
Published
React swipe cards & stack — Tinder-style deck, physics animations, video, custom render. Touch-ready, TypeScript.
Maintainers
Readme
react-cards-pro
Fluid, physics-based React swipe cards and stack — Tinder-style deck, FAANG-quality animations, video support, and custom render. Touch-optimized for mobile and tablet.
Live demo
https://react-cards-pro.vercel.app
Features
- Swipe cards — Tinder-style left/right swipe with physics (framer-motion + @use-gesture)
- Image, video & custom — Use
image/videoorrenderCardfor fully custom React components - Endless mode — Loop the deck; swiped cards recycle to the end
- Auto-swipe — Optional slideshow; pauses on hover/touch
- Mobile-first — Touch-friendly, no native drag steal, responsive
- TypeScript — Full types,
CardItem+ReactCardsProPropsexported
Install
npm i react-cards-proUsage
import { ReactCardsPro } from 'react-cards-pro';
const data = [
{ id: '1', image: '/photo.jpg', title: 'Card 1' },
{ id: '2', image: '/photo2.jpg', video: '/video.mp4', title: 'Card 2' },
];
<ReactCardsPro
data={data}
messyStack
onSwipe={(direction, item) => console.log(direction, item)}
/>Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| data | CardItem[] | — | Array of cards: { id, image?, video?, title? }. image optional when using renderCard. |
| stackDepth | number | 3 | Max cards in DOM (active + next N−1). |
| scaleRatio | number | 0.05 | Scale step between stacked cards. |
| yOffset | number | -10 | Vertical offset (px) per stack level. |
| cardMaxWidth | number | 380 | Max width (px) of the card stack. |
| messyStack | boolean | true | Random rotation on background cards. |
| scatterRandomness | number | 5 | Max scatter rotation (deg). |
| animateRotation | boolean | true | Map drag to rotation. |
| animateScale | boolean | true | Map drag to scale. |
| swipeThreshold | number | 150 | Min drag (px) to trigger swipe. |
| maxRotation | number | 15 | Max rotation (deg) at threshold. |
| endless | boolean | false | When true, swiped cards move to the end so the deck never empties. |
| autoSwipe | boolean | false | Enable slideshow-style auto-swipe. |
| autoSwipeDirection | 'alternating' \| 'right' \| 'left' | 'alternating' | Direction for auto-swipe. |
| autoSwipeInterval | number | 4000 | Interval (ms) between auto-swipes. |
| disableAudioControls | boolean | false | Hide custom mute/volume overlay on video cards. |
| hideMuteButton | boolean | false | When true, hides the mute button on video cards. |
| initialMuted | boolean | true | Videos start muted. |
| onSwipe | (direction: string, item: CardItem) => void | — | Called when a card is swiped. |
| onClick | (item: CardItem) => void | — | Called when the active card is clicked/tapped (minimal drag, no swipe). |
| renderCard | (item, { depth, isActive }) => ReactNode | — | Custom render for each card. Overrides image/video when provided. |
Custom cards
Use renderCard to render your own React component instead of image/video:
<ReactCardsPro
data={data}
renderCard={(item, { depth, isActive }) => (
<div className="p-6">
<h2>{item.title}</h2>
<p>{item.description}</p>
{isActive && <span>Active</span>}
</div>
)}
onSwipe={(dir, item) => console.log(dir, item)}
/>renderCard receives the CardItem and { depth, isActive }. Your component is wrapped in the same card chrome (border-radius, shadow, gestures).
Endless mode
<ReactCardsPro
data={data}
endless
onSwipe={(dir, item) => console.log('Swiped', dir, item.title)}
/>With endless={true}, each swiped card is moved to the back of the list so the stack loops forever.
Mobile & tablet
- Gestures use touch-friendly defaults and pointer capture.
- Images and videos are non-draggable so the browser doesn’t steal drags.
- The stack uses
touch-action: noneand responsive layout (width: 100%,aspectRatio: 3/4,maxWidth: 380).
Links
- Live demo: react-cards-pro.vercel.app
- npm: react-cards-pro on npm
- Author: Don Sirivat (LinkedIn)
License
MIT
