Split Stack

A stack of cards where the front card splits down the middle, both halves swing out, hop back through the stack one card at a time, then rejoin at the back. Infinite loop with smooth Framer Motion animations.

Installation

  1. 1

    Install the component:

    npx shadcn@latest add https://ui.amines.fun/r/split-stack.json
  2. 2

    Usage:

    jsx

    app/page.jsx

      <SplitStack        items={[          {            title: "Blue hour",            icon: <Sparkles />,            image:              "https://images.unsplash.com/photo-1789758612877-fa37f9689a20?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=NHwxMjA3fDA%3D",          },          {            title: "Dusk",            icon: <Crop />,            image:              "https://images.unsplash.com/photo-1789758612877-fa37f9689a20?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=NHwxMjA3fDA%3D",          },          {            title: "Pink drift",            icon: <Cloud />,            image:              "https://images.unsplash.com/photo-1789758612877-fa37f9689a20?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=NHwxMjA3fDA%3D",          },          {            title: "Pink drift",            icon: <Cloud />,            image:              "https://images.unsplash.com/photo-1789758612877-fa37f9689a20?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=NHwxMjA3fDA%3D",          },        ]}        duration={1.8}        split={34}        hopTime={0.2}        theme={{ card: "#1d1c22", edge: "#FF7138" }}        spring={{ type: "spring", stiffness: 200, damping: 26 }}      />

Props

PropTypeDefaultDescription
itemsArray<{ id?: string; title: string; icon?: ReactNode; image?: string; background?: string; content?: ReactNode }>6 built-in gradient cards (Blue hour, Moonrise, Dusk, Pink drift, First light, Tide)Array of card items. Each item can have a title, optional icon (Lucide React component), image URL, CSS background (gradient/color), or custom content that replaces the image area.
visiblenumber4Maximum number of cards drawn in the stack at once. Additional cards wait out of sight and fade in as the stack moves forward.
autoplaybooleantrueEnable automatic cycling through cards.
delaynumber1600Milliseconds of rest between sweeps (animation cycles).
openTimenumber0.5Seconds for the split to open (front card halves swing apart).
hopTimenumber0.36Seconds for each hop past one card. Total animation time grows with the stack size.
closeTimenumber0.5Seconds for the halves to rejoin at the back of the stack.
holdnumber0.25Share of each hop spent resting behind a card (0.05 to 0.8). Higher values = longer pause between hops.
hopArcnumber2Small vertical hop per card, in % of card height. 0 = no vertical movement.
splitStaggernumber0.06Seconds the right half lags the left during split (organic feel).
pauseOnHoverbooleantruePause autoplay when pointer enters the component.
clickToAdvancebooleantrueClick the front card to trigger an immediate sweep.
sizenumber1Scales the whole stack proportionally.
aspectnumber1.38Card width / height ratio.
radiusnumber4.4Corner radius as a % of card width.
spacing{ x: number; y: number; z: number }{ x: 13, y: -11, z: -90 }Offset per card back. x, y in % of the card, z in px (keep negative for depth).
tilt{ x: number; y: number; z: number }{ x: 0, y: 0, z: 0 }Degrees of rotation for the entire stack. Flat by default so every card is a true rectangle.
perspectivenumber1400Perspective in px. 0 = none (every card the same size, no depth scale).
perspectiveOriginstring"50% 45%"CSS perspective-origin for the 3D transform.
splitnumber34How far each half swings out, in % of card width.
liftnumber72Pixels each half comes toward you (capped below the z spacing).
splitRotatenumber5Degrees each half rolls. Mirrored so both sides match.
splitTurnnumber0Degrees each half turns in 3D. Anything above 0 makes trapezoids.
dimnumber0.17How much darker each card gets per step back (0-1).
shadowstring"0 34px 60px -26px rgba(0,0,0,0.75)"CSS box-shadow under the cards.
theme{ card: string; border: string; highlight: string; text: string; badge: string; badgeText: string; dim: string; edge: string }{ card: "#2a2931", border: "rgba(255,255,255,0.07)", highlight: "rgba(255,255,255,0.06)", text: "#f4f4f6", badge: "rgba(255,255,255,0.08)", badgeText: "rgba(255,255,255,0.7)", dim: "#0b0a10", edge: "#ffffff" }Complete color theme for the stack. All values are CSS color strings.
springobject{ type: "spring", stiffness: 170, damping: 24, mass: 1 }Framer Motion transition for cards moving forward between slots.
openEasearray[0.22, 1, 0.36, 1]Cubic bezier for the split opening animation.
hopEasearray[0.65, 0, 0.35, 1]Cubic bezier for each hop animation.
closeEasearray[0.45, 0, 0.2, 1]Cubic bezier for the rejoin animation.
minHeightnumber360Minimum height in px used when the parent has no explicit height.
classNamestring""Additional CSS classes for the root element.