Scene
componentCreates a pinned, scroll-driven scene. Provides a progress value (0→1) to children as you scroll through its duration. Uses CSS position: sticky under the hood.
<Scene duration="200vh">
{(progress) => (
<div style={{ opacity: progress }}>
{Math.round(progress * 100)}%
</div>
)}
</Scene>TextReveal
componentProgressively reveals text as scroll progresses. Supports word-by-word, character-by-character, or line-by-line reveal modes.
<TextReveal
mode="word"
progress={progress}
at={0}
span={0.8}
>
Your text reveals progressively
as the user scrolls.
</TextReveal>Reveal
componentReveals elements with entrance animations triggered at a specific scroll progress. Five built-in animations: fade, fade-up, fade-down, scale, and blur.
<Reveal
animation="fade-up"
at={0.3}
duration={600}
>
<div>I appear on scroll!</div>
</Reveal>Counter
componentAnimates numbers from a start value to an end value based on scroll progress. Supports custom formatting, easing, and configurable start/span ranges.
<Counter
from={0}
to={1000}
progress={progress}
at={0}
span={0.8}
format={(n) => n.toFixed(0)}
/>CompareSlider
componentSide-by-side comparison slider. Supports drag interaction (default) or scroll-driven mode. Drag the handle below to see it in action.
<CompareSlider
before={<img src="before.jpg" />}
after={<img src="after.jpg" />}
/>
{/* Or scroll-driven: */}
<CompareSlider
scrollDriven
progress={progress}
before={...}
after={...}
/>Marquee
componentInfinite looping horizontal ticker. Configurable speed, direction, and gap. Pauses on hover by default. Respects prefers-reduced-motion.
hover to pause
<Marquee speed={40} direction="left" pauseOnHover>
<span>Item 1</span>
<span>Item 2</span>
<span>Item 3</span>
</Marquee>Progress
componentGlobal scroll progress indicator. Three visual types: bar (horizontal/vertical), dots (discrete steps), and ring (circular SVG). Renders at a fixed viewport position.
ring renders as a fixed SVG overlay
<Progress
type="bar"
position="top"
color="#dc2626"
/>
{/* Or with explicit progress: */}
<Progress
type="ring"
progress={progress}
color="#dc2626"
ringSize={48}
/>Parallax
componentCreates parallax scroll effects by moving elements at different speeds relative to scroll. Speed < 1 moves slower (background feel), speed > 1 moves faster (foreground). GPU-accelerated with CSS transforms.
See parallax in action on the landing page
<Parallax speed={0.5} direction="vertical">
<img src="background.jpg" />
</Parallax>
<Parallax speed={1.5}>
<div>I move faster than scroll</div>
</Parallax>HorizontalScroll
componentConverts vertical scrolling into horizontal panel movement. Wrap Panel children inside — each Panel takes up 100vw. Vertical scroll distance equals the number of panels × 100vh.
Requires vertical scroll space. See it on the landing page
<HorizontalScroll>
<Panel>
<div>Slide 1</div>
</Panel>
<Panel>
<div>Slide 2</div>
</Panel>
<Panel>
<div>Slide 3</div>
</Panel>
</HorizontalScroll>VideoScroll
componentScrubs a video frame-by-frame based on scroll position — the same technique Apple uses in keynote product pages. Pins the video while scrubbing. Supports overlay content via render function children.
<VideoScroll
src="/hero.mp4"
duration="300vh"
pin
>
{(progress) => (
<div style={{ opacity: progress > 0.5 ? 1 : 0 }}>
Overlay content appears midway
</div>
)}
</VideoScroll>StickyHeader
componentA fixed header that transitions from transparent to an opaque background with optional backdrop blur after scrolling past a configurable threshold. The header at the top of this page is a live StickyHeader.
<StickyHeader> — scroll to see it transition<StickyHeader
threshold={80}
background="rgba(0, 0, 0, 0.9)"
blur
>
<nav>Your nav content</nav>
</StickyHeader>Kino
providerRoot provider that initializes the global scroll tracker. All scroll-driven components must be wrapped inside Kino. Also exposes a useKino() hook for accessing the scroll tracker directly.
<Kino>import { Kino, Scene, Progress } from "react-kino";
export default function App() {
return (
<Kino>
<Progress type="bar" position="top" />
<Scene duration="200vh">
{(progress) => <div>{progress}</div>}
</Scene>
</Kino>
);
}Hooks
3 hooksLow-level hooks for custom scroll-driven logic.
useScrollProgress()Returns the global page scroll progress as a number from 0 to 1. Used internally by Progress and other components.
const progress = useScrollProgress();
// 0 at top of page → 1 at bottomuseSceneProgress()Tracks scroll progress within a specific element. Takes a ref and duration in pixels, returns 0→1 progress.
const ref = useRef<HTMLDivElement>(null);
const progress = useSceneProgress(ref, 1000);useIsClient()SSR hydration guard. Returns false during server render, true after client hydration. Use to protect scroll-dependent calculations.
const isClient = useIsClient();
if (!isClient) return <Fallback />;