Skip to content
WANCRAFT

H.1513D & Experimental

Page Flip

A CSS 3D book: drag a page's edge and it turns around the spine with curl shading, or falls back.

NewReactMotionCSSTailwindadvanced

Overview

Page Flip lays your pages out as sheets hinged at a spine in CSS 3D — each sheet carries a right-hand page on its front and a left-hand page on its back. Wide containers show two-page spreads (the cover sits alone on the right, the book recentring as you open it); narrow ones switch to single pages, or you can force either view. Drag a page's outer edge and it follows the pointer exactly — the edge tracks your cursor around the spine — then completes or falls back depending on how far past the spine it went and how fast you let go. Prev/next buttons, the arrow keys and Home/End (while the book is focused) turn pages too, riffling through several at once. A shading gradient sweeps across the sheet as it lifts, and stacked page edges sit under whichever side still holds paper. Only the visible pages are interactive; every other face is inert and hidden from assistive tech, and the spread is announced as "Pages 2–3 of 12". With reduced motion pages change instantly.

01Installation

Method 01 · Registry

CLI verified

Uses the shadcn CLI in a project initialised with shadcn init. Installs the file to components/ui/page-flip.tsx and adds its dependencies.

npx shadcn@latest add https://wancraft.my/r/page-flip.json

Method 02 · Copy and paste

  1. 1. Install the dependencies below.
  2. 2. Copy the source from the Code tab into components/ui/page-flip.tsx.
  3. 3. Import it and adjust props.
npm install motion
Dependencies
motion
Peer
react ≥ 18, tailwindcss ≥ 4
Added
13 Oct 2026
Updated
—

02Usage

The default configuration. Change properties above to generate a tailored example in the Usage tab.

example.tsx
import { PageFlip } from "@/components/ui/page-flip";

export function PageFlipExample() {
  const pages = ["Cover", "Contents", "Restraint", "Timing", "Touch", "Fin"].map((title) => (
    <div key={title} className="flex h-full items-end p-5">
      <p className="text-xl font-semibold tracking-tight">{title}</p>
    </div>
  ));

  return (
    <PageFlip pages={pages} label="Notes on Craft" />
  );
}

03Props

PropTypeDefaultDescription
pagesReactNode[]—Page contents in reading order. Page 1 is the cover, shown alone on the right in spreads.
labelstring"Book"Accessible name of the book.
widthnumber240Page width in px; shrinks to fit narrow containers (min 120).
rationumber1.38Page height as a multiple of its width.
view"auto" | "spread" | "single""auto"Two-page spreads, single pages, or spreads only when two pages fit.
durationnumber700Duration of one full page turn in ms (drags finish proportionally).
shadingnumber0.6Strength of the curl shading on turning pages, 0–1.
foliosbooleantrueSmall page numbers in the outer bottom corners.
showControlsbooleantruePrevious/next buttons and the page counter.
accentstring"#FF7448"Focus ring and control colour.
defaultPage / onPageChangenumber / (page) => void0Initially shown page (0-based); called with the first visible page when it changes.

04Features

  • 01Sheets hinged at the spine in CSS 3D, with a front (right) and mirrored back (left) face
  • 02Edge-follow drag: the page edge tracks the pointer around the spine, then completes or returns by angle and flick speed
  • 03Spread view on wide containers (recentring on the covers), single pages on narrow ones, or forced either way
  • 04Curl shading that sweeps across a sheet as it lifts, gutter shadows and stacked page edges
  • 05Buttons, Left/Right arrows and Home/End; multi-page jumps riffle through the sheets in order
motion · tweeninput · draginput · pointerinput · clickinput · keyboardinput · focus

05Accessibility

  • A <section> with aria-roledescription="book" and a focusable group that turns pages with Left/Right, Home and End.
  • Only the visible pages are interactive: every hidden face (and every turned or covered sheet) is inert and aria-hidden.
  • A polite live region announces "Pages 2–3 of 12" (or "Page 3 of 12" in single view).
  • The drag grips are pointer-only conveniences and are hidden from assistive tech; the buttons and keys do the same job.
  • prefers-reduced-motion turns pages instantly and stops the book from sliding between cover and spread.

06Limitations

  • The drag grip covers the outer 16% of each page; keep interactive page content away from the outer edge.
  • Single view gives each page its own sheet with a blank back, like a notepad.