Concertina Book

A calm lake below dark pines and pale mountains
About this component

Concertina Book

A folded concertina book whose pages carry one wide photo printed across the whole strip. As it opens, each page unfolds in 3D from a tight zigzag pile on the right, catching light and shade on its folds, until the picture lies flat and unbroken. Folds and unfolds on its own loop with autoplay, opens as it passes through the viewport, or follows any progress you hand it (a pinned section's scroll, a slider). Pages, fold angle, shade and page aspect are props; reduced motion shows the flat pages in a swipeable row.

Usage

The import and the props worth knowing about, in one place.

import { ConcertinaBook } from "@/components/beste/component/concertina-book";
import { useScroll } from "framer-motion";

// Opens on its own as it scrolls through the viewport
<ConcertinaBook
  className="h-[32rem]"
  image={{ src: "https://images.unsplash.com/photo-1506744038136-46273834b3fb?w=2400&q=80", alt: "A calm lake below pines" }}
  pages={6}          // number of folded pages
  fold={78}          // largest fold angle, in degrees
  shade={0.5}        // light and shade on the folds, 0 to 1
/>

// Driven by a pinned section: scrolling down turns into sideways travel
function Pinned() {
  const ref = useRef<HTMLElement>(null);
  const { scrollYProgress } = useScroll({ target: ref, offset: ["start start", "end end"] });
  return (
    <section ref={ref} className="relative h-[320vh]">
      <div className="sticky top-0 h-svh">
        <ConcertinaBook className="h-full" image={...} progress={scrollYProgress} />
      </div>
    </section>
  );
}

Props

Read from the component's own type, so this cannot drift from what it accepts.

PropTypeDefaultDescription
image*{ src: string; alt: string }—One wide photo, printed across every page of the book
pagesnumber—Number of folded pages
foldnumber—Largest fold angle of a closed page, in degrees
shadenumber—Light and shade on the folds, 0 to 1
pageAspectnumber—Page width divided by page height
progressMotionValue<number> | number—How far the book has opened, 0 to 1. Pass a MotionValue (for example a pinned section's scroll progress) or a number; when omitted the book opens as it passes through the viewport.
autoplayboolean—Fold and unfold on a loop by itself, with no scroll involved (ignored when `progress` is given)
cyclenumber—Seconds for one open-and-close loop when autoplaying
pausedboolean—Hold the pages where they are
classNamestring—

More Media components

View all Media
Orange poppies against a clear blue sky
Violinists of an orchestra playing under warm stage light

Built around the light.

Curved white bands of a building rising around an opening of blue sky