A stack of cards you sort one at a time by swiping left or right. Buttons and arrow keys do the same thing.

Turquoise lake
4.2 km loop · Easy
Drag a card, use the buttons, or press the arrow keys.
pnpm dlx shadcn@latest add @latheui/swipe-deckPart of Lathe Pro. Set up your project once with your license key: npx latheui init --key <key>. See Lathe Pro.
Swipe Deck is part of Lathe Pro
The preview is live and free to try. The source, the install and every assembly come with Pro: $79 once, with lifetime updates.
Depends on
Tracks which cards are gone internally. Change its key to reset it. Also accepts native div attributes.
| Prop | Type | Default | Description |
|---|---|---|---|
| items* (required) | T[] | — | The cards, top first. |
| getId* (required) | (item: T) => string | — | Stable, unique id for a card. |
| getLabel* (required) | (item: T) => string | — | Plain-text name, used for the card's name and for announcements. |
| renderCard* (required) | (item: T) => ReactNode | — | Card content. |
| label* (required) | string | — | Accessible name of the deck. |
| onSwipe | (item: T, direction: "left" | "right") => void | — | Called when a card leaves the deck. |
| labels | { left: string; right: string } | { left: "Skip", right: "Save" } | Names of the two outcomes, for the buttons, stamps and announcements. |
| empty | ReactNode | "You are all caught up." | Shown when no cards are left. |
| threshold | number | 110 | Drag distance in pixels past which releasing commits the swipe. |
onSwipe={(item, direction) => {
save(item, direction)
toast(`${direction === "right" ? "Saved" : "Skipped"} ${item.name}`, {
action: { label: "Undo", onClick: () => revert(item) },
})
}}The deck is 4:5 and fills its width. Change the width on the root and the ratio inside the file.
<SwipeDeck className="max-w-sm" … />