react-magazine
v1.0.3
Published
A lightweight React component for realistic page-flip animations, featuring built-in navigation controls, full TypeScript support, and easy style customization.
Downloads
175
Maintainers
Readme
react-magazine
React component for creating realistic magazine-style page flip animations with built-in controls and full TypeScript support.
Demo

Installation
npm install react-magazineQuick Start
import { MagazineBook, Page } from 'react-magazine';
const images = [
"https://picsum.photos/id/1/400/500",
"https://picsum.photos/id/2/400/500",
"https://picsum.photos/id/3/400/500",
"https://picsum.photos/id/4/400/500",
"https://picsum.photos/id/5/400/500",
"https://picsum.photos/id/6/400/500",
];
function App() {
return (
<MagazineBook width={400} height={500} showCover={true} showControls={true}>
{images.map((img, index) => (
<Page key={index} number={index + 1}>
<img
src={img}
alt={`Page ${index + 1}`}
style={{ width: "100%", height: "100%", objectFit: "cover" }}
/>
</Page>
))}
</MagazineBook>
);
}
export default App;Features
- Realistic page flip animation
- Built-in navigation controls
- Hard/soft page density support
- Responsive design (fixed/stretch modes)
- Portrait and landscape orientation
- Touch and mouse support
- TypeScript support
- SSR compatible (with dynamic import)
- Zero configuration - styles are built-in
Using the useFlipBook Hook
import { MagazineBook, Page, useFlipBook } from 'react-magazine';
const images = [
"https://picsum.photos/id/1/400/500",
"https://picsum.photos/id/2/400/500",
"https://picsum.photos/id/3/400/500",
"https://picsum.photos/id/4/400/500",
];
function App() {
const { bookRef, state, flipNext, flipPrev, handlers } = useFlipBook();
return (
<div>
<MagazineBook ref={bookRef} width={400} height={500} {...handlers}>
{images.map((img, index) => (
<Page key={index} number={index + 1}>
<img
src={img}
alt={`Page ${index + 1}`}
style={{ width: "100%", height: "100%", objectFit: "cover" }}
/>
</Page>
))}
</MagazineBook>
<div>
<button onClick={() => flipPrev()}>Previous</button>
<span>Page {state.currentPage + 1} of {state.pageCount}</span>
<button onClick={() => flipNext()}>Next</button>
</div>
</div>
);
}
export default App;Props
MagazineBook Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| width | number | 400 | Page width in pixels |
| height | number | 300 | Page height in pixels |
| size | 'fixed' \| 'stretch' | 'fixed' | Size mode |
| startPage | number | 0 | Starting page index |
| showCover | boolean | false | Makes first & last pages hard (like book covers) |
| showControls | boolean | false | Show built-in navigation controls |
| drawShadow | boolean | true | Draw shadow when flipping |
| flippingTime | number | 1000 | Flip animation duration (ms) |
| usePortrait | boolean | false | Use portrait mode |
| mobileScrollSupport | boolean | true | Enable mobile scroll |
| swipeDistance | number | 30 | Swipe distance threshold |
| showPageCorners | boolean | true | Show page corner fold on hover |
| disableFlipByClick | boolean | false | Disable click to flip |
| clickEventForward | boolean | true | Forward click events to children |
| useMouseEvents | boolean | true | Enable mouse/touch events |
| maxShadowOpacity | number | 1 | Shadow intensity (0-1) |
| autoSize | boolean | true | Auto-resize based on container |
| isLoading | boolean | false | Show loading state |
| disabled | boolean | false | Disable all interactions |
| controlsClassName | string | '' | Custom class for controls |
| controlsStyle | CSSProperties | {} | Custom style for controls |
Event Props
| Prop | Type | Description |
|------|------|-------------|
| onFlip | (e: FlipEvent) => void | Called when page flips |
| onChangeState | (e: StateEvent) => void | Called when state changes |
| onChangeOrientation | (e: OrientationEvent) => void | Called when orientation changes |
| onInit | (e: FlipEvent) => void | Called when initialized |
| onUpdate | (e: FlipEvent) => void | Called when updated |
Page Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| number | number | - | Page number (for display) |
| density | 'soft' \| 'hard' | 'soft' | Page density (soft bends, hard doesn't) |
| className | string | '' | Custom class |
| style | CSSProperties | {} | Custom style |
showCover Behavior
When showCover={true}:
- First page automatically becomes hard (doesn't bend)
- Last page automatically becomes hard (doesn't bend)
- All inner pages remain soft (paper flip effect)
import { MagazineBook, Page } from 'react-magazine';
function App() {
return (
<MagazineBook showCover={true}>
<Page>Front Cover (auto hard)</Page>
<Page>Page 2 (soft - bends)</Page>
<Page>Page 3 (soft - bends)</Page>
<Page>Back Cover (auto hard)</Page>
</MagazineBook>
);
}
export default App;Ref API Methods
Access via bookRef.current:
| Method | Description |
|--------|-------------|
| flipNext(corner?) | Flip to next page |
| flipPrev(corner?) | Flip to previous page |
| flip(pageNum, corner?) | Flip to specific page with animation |
| turnToPage(pageNum) | Jump to page without animation |
| getCurrentPageIndex() | Get current page index (0-based) |
| getPageCount() | Get total page count |
| getOrientation() | Get current orientation |
| getState() | Get current state |
| pageFlip() | Get underlying PageFlip instance |
useFlipBook Hook
Returns:
| Property | Type | Description |
|----------|------|-------------|
| bookRef | RefObject | Ref to attach to MagazineBook |
| state | object | { currentPage, pageCount, orientation, pageState, isFlipping } |
| flipNext | function | Flip to next page |
| flipPrev | function | Flip to previous page |
| flipTo | function | Flip to specific page |
| turnTo | function | Jump without animation |
| canFlipNext | function | Check if can flip next |
| canFlipPrev | function | Check if can flip prev |
| handlers | object | Event handlers to spread on MagazineBook |
Next.js Usage
import dynamic from 'next/dynamic';
const MagazineBook = dynamic(
() => import('react-magazine').then((mod) => mod.MagazineBook),
{ ssr: false }
);
const Page = dynamic(
() => import('react-magazine').then((mod) => mod.Page),
{ ssr: false }
);
function App() {
return (
<MagazineBook width={400} height={500} showControls>
<Page number={1}>Page 1</Page>
<Page number={2}>Page 2</Page>
</MagazineBook>
);
}
export default App;TypeScript
All types are exported:
import type {
PageFlipInstance,
IFlipSetting,
IEventProps,
PageProps,
FlipEvent,
OrientationEvent,
StateEvent,
PageDensity,
PageOrientation,
PageState,
FlipCorner,
SizeType,
} from 'react-magazine';License
MIT
