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.
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>
);
}Read from the component's own type, so this cannot drift from what it accepts.
| Prop | Type | Default | Description |
|---|---|---|---|
image* | { src: string; alt: string } | — | One wide photo, printed across every page of the book |
pages | number | — | Number of folded pages |
fold | number | — | Largest fold angle of a closed page, in degrees |
shade | number | — | Light and shade on the folds, 0 to 1 |
pageAspect | number | — | Page width divided by page height |
progress | MotionValue<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. |
autoplay | boolean | — | Fold and unfold on a loop by itself, with no scroll involved (ignored when `progress` is given) |
cycle | number | — | Seconds for one open-and-close loop when autoplaying |
paused | boolean | — | Hold the pages where they are |
className | string | — |