Split Stack Particles

A photo-card stack where the front card breaks into animated mosaic blocks, scatters, travels through the stack, and reforms at the back. Includes reduced-motion handling, hover controls, and per-card styling.

Installation

  1. 1

    Install the component:

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

    Usage:

    jsx

    app/page.jsx

    import SplitStackParticles from "@/registry/components/Cards/SplitStackParticles";export default function Page() {  return (    <div className="h-[520px] w-full">      <SplitStackParticles visible={5} theme={{ edge: "#FF7138" }} />    </div>  );}

Props

PropTypeDefaultDescription
itemsArray<SplitStackParticlesItem>Five built-in photo cardsCards to render. Each item supports id, title, subtitle, icon (ReactNode), image (URL), color, background (CSS background), and content (ReactNode). Images are used as the card face and particle texture; color or theme.card is used when there is no image.
visiblenumber5Maximum number of cards drawn in the stack.
autoplaybooleantrueAutomatically advance the front card through the stack. Autoplay is disabled when reduced motion is requested.
delaynumber1600Rest time between animation sweeps, in milliseconds.
from"right" | "left" | "top" | "bottom" | "center""right"Edge or point from which the blocks begin to break away.
drift[number, number]Derived from from (right: [1, -0.3], left: [-1, -0.3], top: [0.35, -1], bottom: [0.35, 1], center: [0.7, -0.5])Optional [x, y] direction for the particle cloud. Overrides the direction derived from from.
blocksnumber28Smallest grid size across the card, clamped between 8 and 60. Higher values create finer blocks.
mosaicnumber0.65Controls the mix of large and small blocks. 0 creates a uniform grid; higher values add more large blocks.
raggednumber0.28How unevenly the break front crosses the card, from 0 to 1.
scatternumber46Maximum particle travel distance as a percentage of card width. Travel is clamped to the available space.
spreadnumber1Angular spread of the particle cloud, in radians.
cloudAlphanumber0.6Opacity of the blocks while scattered.
shrinknumber0.2How much blocks shrink while scattered. Set to 0 to keep their size.
tightennumber0.35How much the particle cloud contracts as it travels through the stack. Set to 0 to disable contraction.
glowbooleantrueDraw an accent glow around blocks as they break away and land.
preTimenumber0.12Seconds the hover state settles before the break begins.
dissolveTimenumber0.65Seconds for the break front to cross the card.
scatterTimenumber0.8Seconds for each block to fly away from the card.
holdnumber0.1Extra pause in seconds between the break and the trip through the stack.
hopTimenumber0.42Seconds for the particle cloud to pass one card. Total trip time grows with the stack depth.
mergeTimenumber0.7Seconds for each block to fly back and reform the card.
mergeSpreadnumber0.4Seconds over which block merges are staggered.
mergeOverlapnumber0.5How much of the merge overlaps the end of the trip, from 0 to 1.
landnumber0.016Scale of the small pulse when the card lands. Set to 0 to disable the pulse.
hopArcnumber1.2Height of the cloud's gentle arc through the stack, as a percentage of card height.
hopEasenumber[] | ((progress: number) => number)[0.3, 0.15, 0.7, 0.85]Cubic Bezier control points [x1, y1, x2, y2] or a custom easing function for travel through the stack.
pauseOnHoverbooleantruePause automatic cycling while a pointer is over the component.
clickToAdvancebooleantrueLet a click or keyboard activation advance the front card immediately.
sizenumber1Scales the whole stack proportionally.
aspectnumber1Card width divided by card height.
fallbackAspectnumber1.2Aspect ratio used when the parent does not provide a height.
radiusnumber9.5Card corner radius as a percentage of card width.
spacing{ x?: number; y?: number; z?: number }{ x: 7, y: 0, z: -110 }Offset between cards. x and y are percentages; z is pixels and should remain negative for depth.
tilt{ x?: number; y?: number; z?: number }{ x: 0, y: 0, z: 0 }Rotation of the whole stack in degrees around each axis.
perspectivenumber14003D perspective distance in pixels. Set to 0 to disable perspective.
perspectiveOriginstring"50% 45%"CSS perspective-origin for the 3D stack.
dimnumber0.2Darkening applied to cards farther back in the stack.
shadowstring"0 30px 50px -24px rgba(0,0,0,0.8)"CSS box-shadow drawn under each card.
theme{ card?: string; border?: string; text?: string; textMuted?: string; badge?: string; badgeText?: string; captionBg?: string; dim?: string; edge?: string }Built-in dark themeOptional CSS color overrides for the card, border, text, muted text, badge, badge text, caption background, depth dimming, and particle edge glow.
reserve{ x?: number; y?: number }{ x: 16, y: 6 }Extra free space reserved around the stack for particles, as percentages of card width.
dprnumber1.5Maximum device-pixel ratio for the particle canvas. Lower values reduce canvas rendering cost.
zoomnumber1.06Card image scale at full hover. 1 disables the zoom.
captionbooleantrueShow the title and subtitle caption on the hovered card.
sheenbooleantrueShow the animated sheen on the hovered card.
hoverSpreadnumber0.22How much cards fan out on hover.
hoverPushnumber0.35Additional card movement on hover, relative to the stack spacing.
hoverLiftnumber5Vertical lift on hover, as a percentage of card width.
hoverZnumber24How far the hovered card moves toward the viewer, in pixels. Capped by stack depth.
hoverSpringobject{ type: "spring", stiffness: 300, damping: 28, mass: 0.9 }Framer Motion transition configuration for hover movement.
hoverEasenumber[] | ((progress: number) => number)[0.22, 1, 0.36, 1]Cubic Bezier control points or a custom easing function for hover movement.
hoverTimenumber0.55Hover transition duration in seconds.
classNamestring""Additional CSS classes applied to the root wrapper.