Cards that stick to the top and pile on each other. Each card shrinks and dims a little as the next one slides over it.
Interviews, audits and a clear brief before any pixel moves.
Flows, type and a component library the whole team shares.
Small slices behind flags, tested on real devices.
A calm rollout with monitoring, docs and a clean handover.
npx shadcn@latest add https://hyperblur.dev/r/scroll-sticky-stack.jsonWorks in any React project set up with the shadcn CLI. The file lands in components/hyperblur/scroll-sticky-stack.tsx.
import { ScrollStickyStack } from "@/components/hyperblur/scroll-sticky-stack"
<ScrollStickyStack cards={[{ title: "Discover", text: "Interviews and audits." }, { title: "Design", text: "Flows and type." }]} />| Prop | Type | Default | Description |
|---|---|---|---|
| cards | { title: string; text: string; tag?: string; stat?: string; from?: string; to?: string }[] | 4 sample cards | Cards to stack. `from` and `to` are the gradient colors of the card. |
| top | number | 16 | Distance in pixels between the top of the viewport and the first stuck card. |
| gap | number | 14 | Offset in pixels between stuck cards, so each earlier card peeks out. |
| cardHeight | number | 0.62 | Card height as a fraction of the viewport height, between 0.2 and 1. |
| minScale | number | 0.94 | Scale a card loses per card stacked on top of it. Between 0.6 and 1. |
| scroller | RefObject<HTMLElement | null> | HTMLElement | null | A nested scroll container to follow instead of the window. Ignored when `height` is set. | |
| height | number | string | Renders the component inside its own scroll viewport of this height, useful for cards and embeds. Leave unset to follow the window or `scroller`. | |
| autoplay | boolean | false | Only with `height`. Scrolls the viewport up and down on its own until the visitor scrolls it. Static under reduced motion. |
| accent | string | "#2f7bff" | Focus ring color. |