Swipe Deck

Stacked cards with gesture decisions, controls and undo

A tactile card stack that accepts left and right swipes using distance and velocity, springs back from uncertain gestures, and stays fully usable through visible buttons or arrow keys. Decisions can be undone or reset.

Preview

Weekend idea · 01

A quiet morning

Coffee, a long walk, and an hour with a book before the city wakes up.

2 hoursLow effort

Swipe or use

Installation

Install the component using the CLI.

npx shadcn@latest add https://rohan.run/r/swipe-deck.json

Usage

Import the component:

import { SwipeDeck } from "@/components/rohan/swipe-deck"

Use it in your code:

<SwipeDeck
  items={ideas.map((idea) => ({
    id: idea.id,
    ariaLabel: idea.title,
    content: <IdeaCard idea={idea} />,
  }))}
  approveLabel="Save"
  rejectLabel="Skip"
  onDecision={(item, decision) => updateIdea(item.id, decision)}
/>

Props

PropertyTypeDefaultDescription
itemsSwipeDeckItem[]Cards with stable ids, content and optional accessible names.
thresholdnumber96Horizontal distance in px required to accept a drag.
approveLabel / rejectLabelstring"Approve" / "Reject"Visible and accessible decision labels.
onDecision(item, decision) => voidCalled for every accepted swipe or control action.
onUndo(item, decision) => voidCalled when the latest decision is restored.
onReset() => voidCalled when an exhausted deck starts over.
Components