Pagiflow React
Documentation
Official React integration docs for Pagiflow. Learn component props, usePagiflow hook, custom rendering, imperative methods, loop, autoScroll, grid, lazyLoad, thumbnails, sync, responsive and more usage.
React Integration
Install and use Pagiflow in React with pagiflow/react.
npm i pagiflowimport { Pagiflow, PagiflowSlide } from 'pagiflow/react';
import 'pagiflow/css';
export default function App() {
return (
<Pagiflow id="slider-a" nav loop itemsPerSlide={1}>
{/* PagiflowSlide is recommended for clarity */}
<PagiflowSlide className="my-slide">
<div>Slide 1</div>
</PagiflowSlide>
{/* You can also use plain elements */}
<div>Slide 2</div>
<div>Slide 3</div>
</Pagiflow>
);
}Since Pagiflow interacts with the DOM and window APIs, you must use the 'use client' directive at the top of your component file when using the Next.js App Router.
'use client'; // Required for Pagiflow
import { Pagiflow, PagiflowSlide } from 'pagiflow/react';
import 'pagiflow/css';
export default function NextSlider() {
return (
<Pagiflow loop nav itemsPerSlide={3}>
<PagiflowSlide>Slide 1</PagiflowSlide>
<PagiflowSlide>Slide 2</PagiflowSlide>
<PagiflowSlide>Slide 3</PagiflowSlide>
</Pagiflow>
);
}<html> or <body> tags, causing React hydration warnings. To prevent this, add suppressHydrationWarning to these tags in your layout.tsx.
The usePagiflow hook provides a headless way to integrate Pagiflow into your own components, giving you full control over the DOM structure.
import { usePagiflow } from 'pagiflow/react';
function MyCustomSlider() {
const { sliderRef, instance, next, prev, goTo, play, pause, togglePlayPause, setOptions, reInit, currentIndex } = usePagiflow({
loop: true,
itemsPerSlide: 1
});
return (
<div className="custom-container">
<div className="controls">
<button onClick={prev}>Previous</button>
<span>Slide {currentIndex + 1}</span>
<button onClick={next}>Next</button>
<button onClick={() => goTo(0)}>First</button>
<button onClick={play}>Play</button>
<button onClick={pause}>Pause</button>
<button onClick={togglePlayPause}>Toggle</button>
<button onClick={() => setOptions({ gap: 24 }, true)}>Gap 24</button>
<button onClick={() => reInit({ loop: false })}>ReInit</button>
<span>Ready: {instance ? 'yes' : 'no'}</span>
</div>
<div ref={sliderRef} className="my-slider">
<div className="slide-1">Slide 1</div>
<div className="slide-2">Slide 2</div>
</div>
</div>
);
}Use renderNav and renderPagination to inject custom UI that reacts to the slider state.
<Pagiflow
renderNav={({ next, prev, currentIndex }) => (
<div className="my-custom-nav">
<button onClick={prev}>Left</button>
<button onClick={next}>Right</button>
</div>
)}
renderPagination={({ goTo, currentIndex, total }) => (
<div className="my-dots">
{Array.from({ length: total }).map((_, i) => (
<button
key={i}
className={currentIndex === i ? 'active' : ''}
onClick={() => goTo(i)}
/>
))}
</div>
)}
>
{/* slides */}
</Pagiflow>const options = {
nav: true,
loop: true,
itemsPerSlide: 3,
autoplay: true,
autoplayDelay: 2500
};
<Pagiflow {...options}>...</Pagiflow>import { useRef } from 'react';
import { Pagiflow, type PagiflowHandle } from 'pagiflow/react';
export default function SliderControls() {
const sliderRef = useRef<PagiflowHandle | null>(null);
return (
<>
<button onClick={() => sliderRef.current?.next()}>Next</button>
<button onClick={() => sliderRef.current?.prev()}>Prev</button>
<button onClick={() => sliderRef.current?.goTo(2)}>Go to 3rd</button>
<button onClick={() => sliderRef.current?.play()}>Play</button>
<button onClick={() => sliderRef.current?.pause()}>Pause</button>
<button onClick={() => sliderRef.current?.setOptions({ gap: 24 }, true)}>Update Options</button>
<button onClick={() => sliderRef.current?.reInit()}>ReInit</button>
<Pagiflow ref={sliderRef} nav loop itemsPerSlide={1}>
{/* slides */}
</Pagiflow>
</>
);
}PagiflowHandle type for your useRef to get full autocomplete and type safety for imperative methods like next(), prev(), and play(). If using plain JavaScript (.jsx), you can omit this type.
Complete example using both Pagiflow component methods and usePagiflow hook methods.
import { useRef } from 'react';
import {
Pagiflow,
PagiflowSlide,
type PagiflowHandle,
usePagiflow,
} from 'pagiflow/react';
import 'pagiflow/css';
export default function Example() {
const sliderRef = useRef<PagiflowHandle | null>(null);
const {
sliderRef: customRef,
instance,
currentIndex,
next,
prev,
goTo,
play,
pause,
togglePlayPause,
setOptions,
reInit,
} = usePagiflow({
loop: true,
nav: true,
autoplay: true,
autoplayDelay: 2500,
itemsPerSlide: 1,
});
return (
<div>
<h3>Component API + Ref Methods</h3>
<button onClick={() => sliderRef.current?.prev()}>Prev</button>
<button onClick={() => sliderRef.current?.next()}>Next</button>
<button onClick={() => sliderRef.current?.goTo(2)}>Go to 3</button>
<button onClick={() => sliderRef.current?.resume()}>Resume</button>
<Pagiflow ref={sliderRef} loop nav paginate onSlideChange={(i) => console.log(i)}>
<PagiflowSlide>Slide A</PagiflowSlide>
<PagiflowSlide>Slide B</PagiflowSlide>
<PagiflowSlide>Slide C</PagiflowSlide>
</Pagiflow>
<hr />
<h3>usePagiflow Hook API</h3>
<button onClick={prev}>Prev</button>
<button onClick={next}>Next</button>
<button onClick={() => goTo(0)}>First</button>
<button onClick={play}>Play</button>
<button onClick={pause}>Pause</button>
<button onClick={togglePlayPause}>Toggle</button>
<button onClick={() => setOptions({ gap: 24 }, true)}>Gap 24</button>
<button onClick={() => reInit({ loop: false })}>ReInit</button>
<p>Current index: {currentIndex}</p>
<p>Real index (core): {instance?._getRealIndex?.()}</p>
<div ref={customRef} className="my-slider">
<div className="slide-1">One</div>
<div className="slide-2">Two</div>
<div className="slide-3">Three</div>
</div>
</div>
);
}Thumbnail Navigation
Show thumbnail strip that syncs with the main slider. Supports top, bottom, left, and right positions.
| Option | Type | Default | Description |
|---|---|---|---|
| thumbnails.enabled | boolean | false | Enable thumbnails. |
| thumbnails.position | string | 'bottom' | 'top', 'bottom', 'left', 'right'.
|
| thumbnails.thumbWidth | number|string | 80 | Width of each thumbnail. |
| thumbnails.gap | number | 5 | Gap between thumbnails. |
| thumbnails.sidebarHeight | string|number | null | Height for left/right sidebar mode. |
import { Pagiflow, PagiflowSlide } from 'pagiflow/react';
import 'pagiflow/css';
<Pagiflow
id="gallery-slider"
loop
thumbnails={{
enabled: true,
position: 'bottom',
thumbWidth: 90,
gap: 6
}}
>
<PagiflowSlide><img src="/img/1.jpg" alt="1" /></PagiflowSlide>
<PagiflowSlide><img src="/img/2.jpg" alt="2" /></PagiflowSlide>
<PagiflowSlide><img src="/img/3.jpg" alt="3" /></PagiflowSlide>
</Pagiflow>
Slider Sync
Connect two slider instances together for synchronized navigation, ideal for galleries, thumbnail previews, and dual-slider layouts.
| Option | Type | Default | Description |
|---|---|---|---|
| sync | string|instance | null | CSS selector or Pagiflow instance to sync with. |
import { Pagiflow, PagiflowSlide } from 'pagiflow/react';
<Pagiflow id="slider-a" loop>
<PagiflowSlide>Main 1</PagiflowSlide>
<PagiflowSlide>Main 2</PagiflowSlide>
<PagiflowSlide>Main 3</PagiflowSlide>
</Pagiflow>
<Pagiflow id="slider-b" nav loop itemsPerSlide={3} sync="#slider-a">
<PagiflowSlide>Thumb 1</PagiflowSlide>
<PagiflowSlide>Thumb 2</PagiflowSlide>
<PagiflowSlide>Thumb 3</PagiflowSlide>
</Pagiflow>
Responsive Breakpoints
Customize slider behavior across different screen sizes by overriding options at specific responsive breakpoints.
| Option | Type | Default | Description |
|---|---|---|---|
| responsive | object | {} | Map of breakpoint → options. Applied when window.innerWidth >= breakpoint.
|
import { Pagiflow, PagiflowSlide } from 'pagiflow/react';
<Pagiflow
nav
paginate
responsive={{
0: { itemsPerSlide: 1, gap: 0 },
576: { itemsPerSlide: 2, gap: 12 },
768: { itemsPerSlide: 3, gap: 16 },
1200: { itemsPerSlide: 4, gap: 20, autoplay: true }
}}
>
<PagiflowSlide>Slide 1</PagiflowSlide>
<PagiflowSlide>Slide 2</PagiflowSlide>
<PagiflowSlide>Slide 3</PagiflowSlide>
<PagiflowSlide>Slide 4</PagiflowSlide>
</Pagiflow>
Events
Hook into slider lifecycle with the onSlideChange prop.
The onSlideChange prop is the most common way to track the active slide in React. It receives the zero-based real index of the active slide.
import { useState } from 'react';
import { Pagiflow, PagiflowSlide } from 'pagiflow/react';
export default function EventDemo() {
const [active, setActive] = useState(0);
return (
<div>
<div className="status">Current Slide: {active + 1}</div>
<Pagiflow
loop
nav
onSlideChange={(index) => setActive(index)}
>
<PagiflowSlide>Slide 1</PagiflowSlide>
<PagiflowSlide>Slide 2</PagiflowSlide>
<PagiflowSlide>Slide 3</PagiflowSlide>
</Pagiflow>
</div>
);
}
Methods
All methods return this (chainable) unless noted otherwise.
slidesToScroll and loop.
No-ops if already at end without loop.{ silent: false, instant: false }. silent skips rendering;
instant skips animation.
autoplay: true and starts the timer.'dom' to get DOM nodes. No args returns HTML string.
loop is enabled).Chaining example
import { useRef } from 'react';
import { Pagiflow, type PagiflowHandle } from 'pagiflow/react';
const sliderRef = useRef<PagiflowHandle | null>(null);
// Chain on underlying core instance
sliderRef.current?.instance
?.goTo(2)
.setOptions({ autoplay: true, autoplayDelay: 2000 })
.play();
// After 5 seconds, pause
setTimeout(() => {
sliderRef.current?.instance?.pause();
}, 5000);
All Options Reference
Complete list of all configuration options with types and defaults.
| Option | Type | Default | Description |
|---|---|---|---|
| direction | string | 'horizontal' | Slide axis: 'horizontal' or 'vertical'. |
| itemsPerSlide | number | 1 | Visible slides at once. |
| slidesToScroll | number | 1 | Steps per navigation click. |
| gap | number | 8 | Pixels between slides. |
| height | string|number | auto | Viewport height (Required when using vertical, fade, or thumbnails mode.). |
| startIndex | number | 0 | Initial slide index. |
| loop | boolean | false | Infinite loop with DOM clones. |
| speed | number | 400 | Transition duration (ms). |
| animate | boolean | true | Enable CSS transitions. |
| fade | boolean | false | Crossfade instead of slide. |
| nav | boolean | false | Show built-in prev/next buttons. |
| navDisabledEnd | boolean | false | Disable (not hide) buttons at ends. |
| navigation | object | null | External buttons { prev, next }. |
| prevIcon | string | '‹' | Prev button HTML. |
| nextIcon | string | '›' | Next button HTML. |
| prevPosition | string|obj | null | Absolute position for prev button. |
| nextPosition | string|obj | null | Absolute position for next button. |
| paginate | boolean | false | Show pagination dots. |
| paginationPosition | string|obj | null | Custom pagination position. |
| autoplay | boolean | false | Auto-advance slides. |
| autoplayDelay | number | 3000 | Delay between auto advances (ms). |
| pauseOnHover | boolean | true | Pause autoplay on hover. |
| autoScroll | boolean | false | Continuous marquee scrolling. |
| autoScrollSpeed | number | 0.5 | Pixels per animation frame. |
| autoScrollDirection | string | 'left' | 'left' or 'right'. |
| swipeThreshold | number | 60 | Min swipe distance to trigger change. |
| grid | boolean | false | Enable grid mode per slide. |
| gridColumns | number | 2 | Grid column count. |
| gridFill | boolean | false | Fill last page with recycled items. |
| thumbnails.enabled | boolean | false | Show thumbnail strip. |
| thumbnails.position | string | 'bottom' | top / bottom / left / right. |
| thumbnails.thumbWidth | number | 80 | Thumbnail width in px. |
| thumbnails.gap | number | 5 | Gap between thumbnails. |
| thumbnails.sidebarHeight | string | null | Sidebar height for left/right mode. |
| centerMode | boolean | false | Center active slide with peeking neighbors. |
| centerPadding | number|string | 0 | Side padding for center mode. |
| rtl | boolean | false | Right-to-left mode. |
| keyboard | boolean | false | Arrow key navigation. |
| lazyLoad | boolean | false | IntersectionObserver image lazy load. |
| sync | string|inst | null | Selector or instance to sync with. |
| responsive | object | {} | Breakpoint → options map. |
| html | str|arr | null | Inject initial slide HTML content during initialization. |
Frequently Asked Questions
Common questions about using pagiflow/react.
npm i pagiflow, import from pagiflow/react, and load pagiflow/css.Responsive carousel: use
responsive breakpoints and override itemsPerSlide, gap, and slidesToScroll.Controls: use
PagiflowHandle methods like next(), prev(), goTo(), play(), pause(), resume().Headless usage: use
usePagiflow to get sliderRef, currentIndex, and control methods.Sync: give one slider an
id and pass selector to sync, for example sync="#slider-a".
pagiflow/css is imported and slides are inside a valid Pagiflow or hook container.Next.js errors: add
'use client' and initialize only on client-side.Methods do nothing: ensure ref is attached and not null before calling methods.
Sync not working: verify target id exists and selector matches exactly.
Broken layout after resize: call
reInit() or setOptions(newOptions, true).
npm i pagiflow, then import from pagiflow/react and styles from pagiflow/css.PagiflowHandle and call sliderRef.current?.next(), prev(), goTo(index). For chain calls, use sliderRef.current?.instance.sync="#that-id" on the second slider. Example: first id="slider-a", second sync="#slider-a".responsive prop object to Pagiflow, with breakpoint keys and option overrides (like itemsPerSlide and gap).thumbnails prop on Pagiflow, for example { enabled: true, position: 'bottom', thumbWidth: 90, gap: 6 }.onSlideChange prop: <Pagiflow onSlideChange={(index) => setIndex(index)} />. It returns the active real index (0-based).