Card Stack Deck
motiq/card-stack-deckFreeComponent
A deck that handles like physical cards: every card rides a continuous slot spring (k=90, d=12) and sending the front card drives a 210px side arc, a 150px z-lift and a full rotateY flip that reveals a patterned back before it tucks in behind. Drag, tap, prev/next buttons and arrow keys all drive one state, with an aria-live announcement per shuffle and instant reordering under reduced motion.
Live preview
live · rendered by the registry
Rendered by motiq on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://www.motiq.dev/r/card-stack-deck.jsonSource
1"use client";23import * as React from "react";45import { cn } from "@/lib/utils";6import { useControllableState, useReducedMotion, useVisibilityPause } from "@/lib/motiq";78/* -------------------------------------------------------------------------- */9/* Types */10/* -------------------------------------------------------------------------- */1112export interface CardStackDeckItem {13 /** Stable key. */14 id: string;15 /** Front-face content. Ignored when `renderItem` is supplied. */16 content?: React.ReactNode;17 /** Announced politely when this card reaches the front. Falls back to the id. */18 label?: string;19}2021export interface CardStackDeckItemState {22 /** Index in `items`. */23 index: number;24 /** 0 = front of the deck. */25 slot: number;26 isFront: boolean;27}2829export interface CardStackDeckProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onChange"> {30 /** The cards, front to back at rest. */31 items: CardStackDeckItem[];32 /** Render override for the front face. */33 renderItem?: (item: CardStackDeckItem, state: CardStackDeckItemState) => React.ReactNode;34 /** Shown mid-flip on the card's back. Defaults to a patterned back. */35 cardBack?: React.ReactNode;36 /** Rest-fan geometry per slot: y offset, z depth, rotateZ. */37 fan?: { y?: number; z?: number; rotate?: number };38 /** Peak sideways travel of the sent card, in px. */39 arcWidth?: number;40 /** Peak z-lift of the sent card, in px. */41 lift?: number;42 /** Slot spring for send + ripple. */43 spring?: { stiffness?: number; damping?: number };44 /** Drag/tap the front card to shuffle. */45 dragToShuffle?: boolean;46 /** Render the prev/next buttons. */47 showControls?: boolean;48 /** Scene height in px (leaves room for the fan above the card). */49 height?: number;50 /** Card height in px. */51 cardHeight?: number;52 /** Controlled front-card index. */53 topIndex?: number;54 /** Uncontrolled initial front-card index. */55 defaultTopIndex?: number;56 /** Fires with the new front-card index. */57 onTopChange?: (index: number) => void;58 /** Accessible name for the deck group. */59 label?: string;60 /** Park the loop while scrolled offscreen or the tab is hidden. */61 pauseWhenHidden?: boolean;62 /** Force instant, motion-free reordering regardless of system preference. */63 reducedMotion?: boolean;64}6566/* -------------------------------------------------------------------------- */67// … truncated
What it pulls in
Other registry items
Files it writes
More from motiq
All 100 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Activity Streamactivity-stream | motiq | Components | Free | 1 dep | |
| Adaptive Safe-Zone Gridadaptive-safe-zone-grid | motiq | Components | Free | no deps | |
| Agent Run Timelineagent-run-timeline | motiq | Components | Free | 1 dep | |
| AI Response Streamai-response-stream | motiq | Components | Free | 1 dep | |
| Animated Accordionanimated-accordion | motiq | Components | Free | 2 deps | |
| Animated Buttonanimated-button | motiq | Components | Free | 1 dep | |
| Animated Dialoganimated-dialog | motiq | Components | Free | 2 deps | |
| Animated Gridanimated-grid | motiq | Components | Free | 2 deps |
