KQ-1358 · STACK/EXTRUDE

Stack Extrude

Every word is a real 3D block — a stack of copies at true translateZ depths under an em-based perspective, the sides in a pigment that darkens toward the back — and on arrival the words peel up off the page one after another, each word's height on springs.recoil and its stack spreading on springs.glide while a soft contact shadow widens and pales. The blocks turn to face the pointer on springs.glide and drift home on springs.drift; a press pushes them into the page on springs.flick, nearest first, and they pop back on recoil in a ripple. Arrow keys turn them, holding Space or Enter presses them, and Home or Escape squares them up.

KQ-1358 · STACK/EXTRUDE

Basinworks · cast stone

Poured Stone

Arrow keys turn the words; hold Space to press them into the page.

flat · printed on the page

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/stack-extrude

Props

text
string
default —
The words, each set as its own extruded block.
as
"h1" | "h2" | "h3" | "p" | "span" | "div"
default "p"
The element rendered.
layers
number
default 12
Copies in each word's stack, 2 to 32: few read as stepped slabs, many as a solid.
depth
number
default 0.3
How deep the extrusion runs, em.
tilt
number
default 12
How far the pointer turns the blocks, degrees.
angle
[number, number]
default [12, -18]
The resting angle [rotateX, rotateY], degrees; held still under reduced motion.
face
string
default "var(--foreground)"
Face colour, any CSS colour.
side
string
default "oklch(from var(--accent) 0.56 c h)"
The sides' pigment, any CSS colour.
shade
number
default 0.6
How much the sides darken toward the back, 0 to 1.
shadow
number
default 0.5
Strength of the soft shadow on the page, 0 to 1.
lift
number
default 0.14
The gap between block and page at rest, em.
press
number
default 0.7
How far a press pushes the blocks into the page, 0 to 1.
trigger
"mount" | "inView" | "hover" | "manual"
default "inView"
What lifts the words off the page.
once
boolean
default true
Lift once; false lays the words flat again when it leaves view or the hover ends.
play
boolean
default —
Manual trigger: true lifts, false lays flat.
delay
number
default 0
Wait before the first word lifts, ms.
stagger
number
default 90
Gap between words lifting, ms.
duration
number
default 700
Time scale of the lift springs, ms; their damping ratios are kept.
interactive
boolean
default true
Pointer tilt, press, and keyboard turning.
onPressChange
(pressed: boolean) => void
default —
A press began (true) or ended (false).
onComplete
() => void
default —
The lift has settled.
className
string
default —
Size and type; perspective and depth are in em, so the look holds from caption to hero.