React API Reference
Complete reference for @reelkit/react components, props, and methods.
Reel Props
ReelProps
| Prop | Type | Default | Description |
|---|---|---|---|
count | number | required | Total number of items |
size | [number, number] | - | Width and height as [width, height]. When omitted, auto-measures via ResizeObserver |
itemBuilder | (index, indexInRange, size) => ReactElement | required | Function to render each slide |
direction | 'vertical' | 'horizontal' | 'vertical' | Scroll direction |
initialIndex | number | 0 | Starting index |
loop | boolean | false | Enable infinite loop |
enableWheel | boolean | false | Enable mouse wheel navigation |
wheelDebounceMs | number | 200 | Wheel event debounce in ms |
enableNavKeys | boolean | true | Enable keyboard navigation |
onNavKeyPress | (increment: -1 | 1) => void | - | Custom handler for arrow key navigation. Replaces default prev/next behavior. |
transition | TransitionTransformFn | slideTransition | Transition effect function. Built-in: slideTransition, fadeTransition, flipTransition, cubeTransition, zoomTransition |
transitionDuration | number | 300 | Animation duration in ms |
enableGestures | boolean | true | Enable touch/mouse drag navigation |
swipeDistanceFactor | number | 0.12 | Swipe threshold (0-1) |
rangeExtractor | (index: number, count: number) => number[] | defaultRangeExtractor | Custom function to determine which indexes are rendered |
keyExtractor | (index: number) => string | - | Custom key function for React reconciliation (useful with loop) |
apiRef | RefObject<ReelApi> | - | Ref to access API methods |
className | string | - | CSS class for the container element |
style | CSSProperties | - | Inline styles for the container element |
ariaLabel | string | - | Accessible label for the carousel region, read by screen readers |
Callbacks
| Prop | Type | Description |
|---|---|---|
afterChange | (index, indexInRange) => void | Called after slide change completes |
beforeChange | (index, nextIndex, indexInRange) => void | Called before slide change starts |
onSlideDragStart | (index) => void | Called when drag gesture starts |
onSlideDragEnd | (index) => void | Called when drag gesture ends |
onSlideDragCanceled | (index) => void | Called when drag is canceled |
ReelApi Methods
Access slider methods via apiRef:
const apiRef = useRef<ReelApi>(null);
// Navigation
apiRef.current?.next();
apiRef.current?.prev();
apiRef.current?.goTo(5); // instant
apiRef.current?.goTo(5, true); // animated
// Lifecycle
apiRef.current?.adjust(); // recalculate positions
apiRef.current?.observe(); // start observing keyboard
apiRef.current?.unobserve(); // stop observing keyboard| Method | Type | Description |
|---|---|---|
next() | () => void | Go to next slide |
prev() | () => void | Go to previous slide |
goTo(index, animate?) | (number, boolean?) => Promise | Go to specific slide |
adjust() | () => void | Recalculate slide positions |
observe() | () => void | Start keyboard observation |
unobserve() | () => void | Stop keyboard observation |
ReelIndicator Props
ReelIndicatorProps
| Prop | Type | Default | Description |
|---|---|---|---|
count | number | auto | Total number of items. Auto-connected from parent Reel when nested inside one; pass explicitly when used standalone |
active | number | auto | Current active index. Auto-connected from parent Reel when nested inside one; pass explicitly when used standalone |
direction | 'vertical' | 'horizontal' | 'vertical' | Indicator orientation |
radius | number | 3 | Dot size in pixels |
visible | number | 5 | Max normal-sized dots visible |
gap | number | 4 | Space between dots in pixels |
activeColor | string | '#fff' | Active dot color |
inactiveColor | string | 'rgba(255,255,255,0.5)' | Inactive dot color |
edgeScale | number | 0.5 | Scale for overflow edge dots |
onDotClick | (index: number) => void | - | Callback when a dot is clicked |
className | string | - | Custom CSS class |
style | CSSProperties | - | Custom inline styles |
Observer Components
Observe
Bridges core signals to React rendering without causing parent re-renders. Only the children function re-executes when subscribed signals change.
import { Observe } from '@reelkit/react';
<Observe signals={[controller.state.index]}>
{() => <span>Current: {controller.state.index.value}</span>}
</Observe>| Prop | Type | Default | Description |
|---|---|---|---|
signals | Subscribable[] | required | Signals to subscribe to. Any of them notifying re-runs the children function — and only that function, never the parent. A different signal on a later render is followed in place of the one it replaced. |
children | () => ReactElement | null | required | Render function, re-executed on each change. Read the signal values inside it; a value read outside is captured once and goes stale. |
AnimatedObserve
Subscribes to animated value signals and smoothly interpolates using requestAnimationFrame.
import { AnimatedObserve } from '@reelkit/react';
<AnimatedObserve signal={controller.state.axisValue}>
{(value) => (
<div style={{ transform: `translateY(${value}px)` }} />
)}
</AnimatedObserve>| Prop | Type | Default | Description |
|---|---|---|---|
signal | Signal<AnimatedValue> | required | Signal emitting { value, duration, done? }. A duration above 0 interpolates from the current value to the new one; 0 jumps straight there. |
children | (value: number) => ReactElement | required | Render function receiving the interpolated value for the current frame, committed synchronously so the DOM keeps up with the animation. |
SwipeToClose
<SwipeToClose> wraps its children in a container that follows a vertical swipe and calls onClose once the swipe passes the threshold — the dismiss gesture of the lightbox and the stories player, for a custom overlay of your own. SwipeToCloseProps types its props; SwipeToCloseDirection is 'up' | 'down'.
| Prop | Type | Default | Description |
|---|---|---|---|
direction | SwipeToCloseDirection | required | 'up' dismisses like the lightbox, 'down' like the stories player |
onClose | () => void | required | Called after the swipe passes the threshold and the exit animation ends |
enabled | boolean | true | Turns the gesture off without unmounting |
threshold | number | 0.2 | Fraction of the viewport height the swipe has to cover |
className | string | — | Class on the outer <div> |
children | ReactNode | required | Content that moves with the swipe |
SoundProvider
<SoundProvider> creates one SoundController, muted at first, and hands it to its children through useSoundState. The overlays render one for you; add your own only around a custom player whose controls share a mute state.
Hooks
useBodyLock
Locks body scroll and compensates for scrollbar width shift.
import { useBodyLock } from '@reelkit/react';
// Lock body scroll when overlay is open
useBodyLock(isOpen);useOverlayUrlState
OverlayUrlStateOptions
Builds a URL-state controller for an overlay, which you hand to a *UrlOverlay as its controller prop.
See URL State in the React guide for the walkthrough and examples.
| Option | Type | Default | Description |
|---|---|---|---|
param | string | required | Query parameter carrying the active slide, e.g. "photo". Read on the first render and fixed for the life of the component — remount (give it a key) to change it. |
adapter | UrlAdapter | History API | Navigation system to read and write through. Pass a router-backed adapter in a routed app so the router's own location does not go stale. Read on the first render and fixed for the life of the component — remount to change it. |
codec | { decode(raw) => Id | null; encode(id) => string } | required | Wire format: parameter text ↔ a stable identity, collection-blind. Travels with locator as a matched pair sharing the same Id — spread ...urlIndexKey(() => images.length) for the default ?photo=3 index gallery, or supply your own (base64, slug) so a bookmark survives the gallery being reordered. Read live: the latest render's codec handles the next decode or encode. |
locator | { locate(id) => number | null; locateAsync?(id) => Promise<number | null>; identify(index) => id } | required | Maps the identity to a position and owns its own validity: locate (sync), locateAsync (async fallback for a paginated gallery), identify (writes). For a plain index gallery spread ...urlIndexKey(() => images.length) — it supplies this locator plus the matching codec and bounds ?photo=3 against the live count, so a stale ?photo=99 heals out of the URL instead of opening a slide that was never named. A paginated feed or an identity-keyed gallery supplies its own matched codec + locator instead. Read live: the latest render's locator answers the next lookup, and adding or removing locateAsync between renders takes effect on the next miss. |
useReactRouterUrlAdapter
A UrlAdapter backed by React Router. Pass it as the adapter option of useOverlayUrlState in a routed app so the router stays the single source of navigation truth — writing history.pushState behind the router leaves its location stale and its next navigation drops the parameter. Writes touch the query only, so the pathname and hash ride along untouched. Every change reports whether the router pushed on the same page, replaced, or stepped through history, so a gallery opened from a <Link> closes with one back step.
Ships from its own subpath, so an app without a router never pulls react-router-dom into its bundle. react-router-dom is an optional peer dependency.
import { useReactRouterUrlAdapter } from '@reelkit/react/react-router-url-adapter';
const adapter = useReactRouterUrlAdapter();
const photo = useOverlayUrlState({
param: 'photo',
adapter,
...urlIndexKey(() => images.length),
});useReelContext
useReelContext() reads the ReelContextValue of the nearest parent <Reel>, or returns null outside one. <ReelIndicator> uses it to connect itself; use it in your own controls rendered as <Reel> children, so they follow the slider without props. ReelContext is the context object behind it — provide a value of your own only in a test or a custom wrapper.
| Property | Type | Description |
|---|---|---|
index | Signal<number> | Active slide index; read .value inside Observe |
count | Signal<number> | Total slide count |
goTo | (index: number, animate?: boolean) => Promise<void> | Move to a slide, animated or not |
useSoundState
useSoundState() reads the SoundController from the nearest <SoundProvider> and throws outside one. The reel player, lightbox and stories player wrap their content in a provider, so custom controls you pass through their render props can call it to read or toggle mute.
useFullscreen
useFullscreen({ ref }) drives the Fullscreen API for the element in ref, and exits fullscreen when the component unmounts. UseFullscreenProps is its argument; UseFullscreenResult is the tuple it returns.
| Index | Type | Description |
|---|---|---|
[0] | Signal<boolean> | Whether the page is fullscreen; read .value inside Observe |
[1] | () => Promise<void> | Request fullscreen for the element, leaving another fullscreen element first |
[2] | () => Promise<void> | Exit fullscreen |
[3] | () => Promise<void> | Toggle between the two |
Accessibility
<Reel> renders as role="region" with aria-roledescription="carousel". Set the ariaLabel prop to give the region a screen-reader name. A polite live region announces "Slide N of M" on every slide change without re-rendering the carousel. Inactive slides receive the inert attribute so focus and AT navigation skip them.
<ReelIndicator> renders as role="tablist" with roving tabindex on the dots; arrow keys move focus and Enter or Space activates the slide.
Building a custom modal around <Reel>? captureFocusForReturn, createFocusTrap, and getFocusableElements are re-exported from @reelkit/react for focus return and trap.
Utilities
createDefaultKeyExtractorForLoop
Creates a key extractor that handles duplicate indexes when loop is enabled.
import { createDefaultKeyExtractorForLoop } from '@reelkit/react';
<Reel
count={items.length}
size={size}
loop
keyExtractor={createDefaultKeyExtractorForLoop(items.length)}
itemBuilder={...}
/>Size detection
observeElementSize, getViewportSize, observeViewportSize, isMobileWidth, fitAspectRatio, and isTouchDevice are re-exported from @reelkit/react, for a custom overlay that sizes itself the way the reelkit ones do. See Size Detection in the core API.
Autoplay and download
createTimerController, createSlideshowController, and downloadFile are re-exported from @reelkit/react too: the timer behind the stories players, the slideshow behind the lightbox's autoAdvance, and the helper behind its download button. See Autoplay and Download in the core API.