Swipe Deck
A physics, Tinder-style swipeable card deck with throw-to-dismiss, directional intent, and keyboard controls.
A tactile way to page through profiles, testimonials, or onboarding screens. Drag the top card — it rotates with the throw and tints toward your intent; release past the threshold and it flies off while the next card springs forward. Drag, use the buttons, or the arrow keys.
Aria Wells
Product Designer
Mateo Cruz
Staff Engineer
Noah Kim
Founder
Lena Park
Researcher
Installation
pnpm dlx shadcn@latest add "https://godui.design/r/swipe-deck.json"The front card is a draggable spring; its rotation is mapped from the drag
distance and the intent badges fade in as you pass a small offset. A release
past threshold — or a fast enough flick — dismisses it with momentum, and the
deck behind springs up a rank.
Usage
import { SwipeDeck } from "@/components/godui/swipe-deck";<SwipeDeck onSwipe={(index, direction) => save(index, direction)}>
<Card>One</Card>
<Card>Two</Card>
<Card>Three</Card>
</SwipeDeck>Looping
With loop, swiped cards are re-appended so the deck never empties — handy for
testimonial reels.
<SwipeDeck loop>{/* cards */}</SwipeDeck>Custom action labels
<SwipeDeck actions={{ left: "Pass", right: "Connect" }}>{/* cards */}</SwipeDeck>Accessibility
The deck is a focusable group: ← and → swipe, and the
labelled buttons below do the same. When prefers-reduced-motion is set, the
spring settling is removed.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
onSwipe | (index: number, dir: SwipeDirection) => void | — | Fired when the front card is swiped away. |
loop | boolean | false | Re-append swiped cards so the deck never empties. |
threshold | number | 120 | Drag distance (px) past which a release dismisses. |
actions | { left: string; right: string } | — | Labels for the left/right actions and intent badges. |
SwipeDeck also forwards every standard <div> attribute to the root element.