Knit UI
GitHub

Playground

Loading playground…

Playground
<SwipeDeck />

Examples

Default

The default: drag left/right to nope/like, with LIKE / NOPE stamps.

Loading example…

DefaultSourceStorybook

Super Like

Super-like enabled — drag up as well as left/right.

Loading example…

Super LikeSourceStorybook

Fan Effect

The fan effect — cards behind spread out like a hand.

Loading example…

Fan EffectSourceStorybook

Stack Effect

The stack effect — a calm concentric wallet stack.

Loading example…

Stack EffectSourceStorybook

Custom Effect

A custom effect worklet — the extensibility seam. Off-center cards tumble in 3-D depth. Any (state) => ViewStyle worklet plugs in the same way.

Loading example…

Custom EffectSourceStorybook

Imperative Buttons

Buttons drive the deck through the imperative ref — no dragging required.

Loading example…

Imperative ButtonsSourceStorybook

Props

PropTypeDefaultDescription
data requiredT[]The cards, top of the deck first. Consumed as they are swiped away.
renderCard required(item: T, index: number) => ReactElement | nullRender one card's content. Wrapped in the deck's animated + styled host.
accessibilityLabelstring | undefined
directionsSwipeDirection[] | undefinedWhich directions commit a swipe (default `["left", "right"]`).
disabled systemboolean | undefinedDisable dragging (imperative `ref` swipes still work).
effectDeckEffectName | DeckEffect | undefinedCard-transform effect: a built-in name or a custom worklet. Default "tinder".
effectConfigDeckEffectConfig | undefinedTuning for the built-in effects. Ignored when `effect` is a custom worklet.
keyExtractor((item: T, index: number) => string) | undefinedStable keys (recommended). Defaults to the data index.
onActiveIndexChange((index: number) => void) | undefinedFired when the top card changes (after a commit settles).
onEmpty(() => void) | undefinedFired once the deck runs out of cards.
onSwipe((item: T, index: number, direction: SwipeDirection) => void) | undefinedFired when a card is committed in any direction.
onSwipeDown((item: T, index: number) => void) | undefined
onSwipeLeft((item: T, index: number) => void) | undefined
onSwipeRight((item: T, index: number) => void) | undefined
onSwipeUp((item: T, index: number) => void) | undefined
refRef<SwipeDeckRef> | undefined
renderEmpty(() => ReactElement | null) | undefinedRendered once the deck is exhausted (no cards left).
renderStamp((direction: SwipeDirection) => ReactNode) | undefinedPer-direction overlay whose opacity is driven by the drag toward that direction (0 at rest → 1 at the commit threshold). Full control.
stackSizenumber | undefinedHow many cards are mounted/visible in the deck at once (default 3).
stampLabelsPartial<Record<SwipeDirection, string>> | undefinedConvenience built-in stamps — a bordered label per direction, e.g. `{ right: "LIKE", left: "NOPE", up: "SUPER" }`. Superseded by `renderStamp`.
styleFalsy | (ViewStyle | CSSProperties | (CSSProperties & ViewStyle)) | RegisteredStyle<ViewStyle | CSSProperties | (CSSProperties & ViewStyle)> | RecursiveArray<Falsy | (ViewStyle | CSSProperties | (CSSProperties & ViewStyle)) | RegisteredStyl…Container style — set the deck's width/height here.
styles systemSlotStyles<DeckStyles> | undefinedPer-slot style sugar spread onto the matching styled part (`root` / `card` / `stamp`). Explicit props always win.
testIDstring | undefined
thresholdnumber | undefinedCommit distance as a fraction of the card size, 0..1 (default 0.25).
velocityThresholdnumber | undefinedRelease velocity (px/s) that commits a swipe regardless of distance (default 800).

Style slots

Every part of SwipeDeck can be styled through the styles prop. Explicit props on the component always win over slot styles.

SlotUsage
cardstyles={{ card: { … } }}
rootstyles={{ root: { … } }}
stampstyles={{ stamp: { … } }}