ScrollStoryScroll-driven animation,
A shadcn-like primitive for pinned viewport storytelling. Three components. Infinite choreography.
Scroll-driven animation,
composed
A shadcn-like primitive for pinned viewport storytelling. Three components. Infinite choreography.Scroll to explore
Parallax
Depth without effort
One prop. speed controls how fast each layer moves relative to scroll.
<Parallax speed={0.3}>
<BackgroundImage />
</Parallax>
<Parallax speed={0.7}>
<Headline />
</Parallax>
<Parallax speed={1.3}>
<FloatingOrb />
</Parallax>SceneElement
Choreograph anything
Keyframe arrays distribute evenly across the at range. Two values for A→B. Four values for in‑hold‑out.
opacity + y
{ opacity: [0, 1], y: [40, 0] }scale pulse
{ scale: [0.8, 1.05, 1] }rotate
{ rotate: [0, 180, 360] }blur reveal
{ blur: [8, 0], opacity: [0, 1] }Counter
Numbers that scroll
0%
Faster prototyping
0×
Less scroll code
0
Component primitives
<Counter
from={0}
to={47}
suffix="%"
at={[0, 0.5]}
/>Composition
The escape hatch
Custom components consume useSceneProgress() directly for anything the declarative API can't handle.
function OrbitalViz() {
const progress = useSceneProgress();
useMotionValueEvent(progress, "change", (v) => {
// Drive WebGL, canvas, or any
// imperative animation from 0→1
renderer.setProgress(v);
});
return <canvas ref={canvasRef} />;
}Full API
Copy. Paste. Scroll.
ScrollStory
Scene
SceneElement
Parallax
Counter
ProgressIndicator
useStoryProgress()
useSceneProgress()
useSceneId()
Two files. Zero config. Drop into any Next.js project with motion/react.
ScrollStory
Progress: 0.0%