Component Playground

Interactive demos for every react-kino component.
Drag the sliders to simulate scroll progress.

Scene

component

Creates 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.

progress30%
30%
<Scene duration="200vh">
  {(progress) => (
    <div style={{ opacity: progress }}>
      {Math.round(progress * 100)}%
    </div>
  )}
</Scene>

TextReveal

component

Progressively reveals text as scroll progresses. Supports word-by-word, character-by-character, or line-by-line reveal modes.

progress45%
Cinematic scroll-driven storytelling components for React. Build immersive experiences without the complexity.
<TextReveal
  mode="word"
  progress={progress}
  at={0}
  span={0.8}
>
  Your text reveals progressively
  as the user scrolls.
</TextReveal>

Reveal

component

Reveals elements with entrance animations triggered at a specific scroll progress. Five built-in animations: fade, fade-up, fade-down, scale, and blur.

progress0%
Revealed!
animation: fade-up
<Reveal
  animation="fade-up"
  at={0.3}
  duration={600}
>
  <div>I appear on scroll!</div>
</Reveal>

Counter

component

Animates numbers from a start value to an end value based on scroll progress. Supports custom formatting, easing, and configurable start/span ranges.

progress50%
859
Integer
85.9%
Percentage
$43
Currency
<Counter
  from={0}
  to={1000}
  progress={progress}
  at={0}
  span={0.8}
  format={(n) => n.toFixed(0)}
/>

CompareSlider

component

Side-by-side comparison slider. Supports drag interaction (default) or scroll-driven mode. Drag the handle below to see it in action.

{ }
Before
{ }
After
◀▶
<CompareSlider
  before={<img src="before.jpg" />}
  after={<img src="after.jpg" />}
/>

{/* Or scroll-driven: */}
<CompareSlider
  scrollDriven
  progress={progress}
  before={...}
  after={...}
/>

Marquee

component

Infinite looping horizontal ticker. Configurable speed, direction, and gap. Pauses on hover by default. Respects prefers-reduced-motion.

<Scene /><Reveal /><Parallax /><Counter /><TextReveal /><CompareSlider /><HorizontalScroll /><Progress /><Marquee /><Scene /><Reveal /><Parallax /><Counter /><TextReveal /><CompareSlider /><HorizontalScroll /><Progress /><Marquee />

hover to pause

<Marquee speed={40} direction="left" pauseOnHover>
  <span>Item 1</span>
  <span>Item 2</span>
  <span>Item 3</span>
</Marquee>

Progress

component

Global scroll progress indicator. Three visual types: bar (horizontal/vertical), dots (discrete steps), and ring (circular SVG). Renders at a fixed viewport position.

progress60%

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

component

Creates 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.

0.3×
0.6×
1.0×
1.5×

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

component

Converts vertical scrolling into horizontal panel movement. Wrap Panel children inside — each Panel takes up 100vw. Vertical scroll distance equals the number of panels × 100vh.

Panel 1
Panel 2
Panel 3
Panel 4

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

component

Scrubs 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>

Kino

provider

Root 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.

This entire playground is wrapped in <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 hooks

Low-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 bottom
useSceneProgress()

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 />;