Lightbox

A full-screen image and video gallery lightbox component using @reelkit/react-lightbox.

View live demo →

Features

Images & Video
Built-in video slide support
Touch Gestures
Swipe to navigate
Swipe to Close
Swipe up to dismiss
Keyboard Nav
Arrow keys + Escape
Fullscreen
Cross-browser API
Transitions
Slide, fade, flip, zoom-in
Preloading
Adjacent images prefetched
Sound Toggle
Per-slide mute/unmute
Loading States
Spinner + custom render
Error Handling
Error icon + custom render
Render Props
6 customizable render zones
Hooks
useVideoSlideRenderer + useFullscreen

Installation

bash

Don't forget to import the styles:

typescript
Icons
The default controls use lucide-react for icons. If you prefer a different icon library, use renderControls and renderNavigation to provide your own.

Quick Start

The LightboxOverlay component displays images in fullscreen. Pass an array of LightboxItem objects and control visibility with a nullable index.

tsx

Live Demo

LightboxPage.tsx

Click a thumbnail to open the lightbox. Use arrow keys or swipe to navigate.

Video Slides (Opt-in)

Video support is fully opt-in and tree-shakeable — image-only usage pays zero extra bundle cost. Import useVideoSlideRenderer and wire its return values into LightboxOverlay. The hook handles loading states, sound management, and video lifecycle automatically.

tsx
How it works
  • The hook returns SoundProvider — wrap your overlay in it for mute/unmute to work
  • Videos autoplay (muted by default) when the slide becomes active
  • A shared video element is reused across slides for iOS sound continuity
  • Sound button appears automatically on video slides with a reactive mute toggle
  • Items without type: 'video' render as images (backward compatible)

Customization

Custom Controls

Use renderControls to replace the default close button, counter, and fullscreen toggle. Compose with the exported sub-components:

tsx

Custom Info Overlay

Use renderInfo to replace the default title/description gradient, or pass renderInfo={() => null} to hide it entirely:

tsx

Custom Navigation

Use renderNavigation to replace the default prev/next arrows:

tsx

Custom Slide

Use renderSlide for fully custom slide content. Return null to fall back to the default image slide:

tsx

Content Loading & Error Handling

The lightbox tracks per-slide loading and error states. A spinner shows while content loads; a broken-image icon shows for failed media. Errored URLs are cached so revisiting shows the error instantly without retrying.

Lifecycle Callbacks

When using renderSlide, call these callbacks to control the loading indicator:

CallbackWhen to call
onReadyImage loaded or video started playing. Clears loading and error states.
onWaitingVideo is buffering mid-playback. Shows the loading indicator.
onErrorContent failed to load. Shows error overlay and caches the URL as broken.
tsx

Custom Loading & Error UI

Replace the default spinner and error icon with custom components:

tsx

API Reference

Props

PropTypeDefaultDescription
isOpenbooleanrequiredControls lightbox visibility
imagesLightboxItem[]requiredArray of images to display
ariaLabelstring'Image gallery'Accessible label for the dialog region; announced by screen readers when the lightbox opens
initialIndexnumber0Starting image index
transitionFnTransitionTransformFnslideTransitionSlide transition function. Import a built-in (slideTransition, flipTransition, lightboxFadeTransition, lightboxZoomTransition) or pass a custom one. Defaults to slideTransition when omitted.
apiRefMutableRefObject<ReelApi>-Ref to access Reel API
renderControls(props: ControlsRenderProps) => ReactNode-Custom controls, replaces default close button, counter, and fullscreen toggle
renderNavigation(props: NavigationRenderProps) => ReactNode-Custom navigation, replaces default prev/next arrows
renderInfo(props: InfoRenderProps) => ReactNode-Custom info overlay, replaces default title + description gradient. Return null to hide.
renderSlide(props: SlideRenderProps) => ReactNode | null-Custom slide rendering. Receives { item, index, size, isActive, onReady, onWaiting, onError }. Return null to fall back to default.
renderLoading(props: { item: LightboxItem; activeIndex: number }) => ReactNode-Custom loading indicator, replaces default spinner
renderError(props: { item: LightboxItem; activeIndex: number }) => ReactNode-Custom error indicator, replaces default error icon

Callbacks

PropTypeDescription
onClose() => voidCalled when lightbox closes
onSlideChange(index: number) => voidCalled after slide change

Reel Props (proxied)

These props are forwarded to the underlying Reel component.

PropTypeDefaultDescription
loopbooleanfalseEnable infinite loop
enableNavKeysbooleantrueEnable keyboard navigation
enableWheelbooleantrueEnable mouse wheel navigation
wheelDebounceMsnumber200Wheel debounce duration (ms)
transitionDurationnumber300Transition animation duration (ms)
swipeDistanceFactornumber0.12Swipe threshold (0-1)
swipeToCloseDirection'up' | 'down''up'Direction of the swipe-to-close gesture on mobile

Types

LightboxItem

typescript

ControlsRenderProps

typescript
typescript

SlideRenderProps

typescript

InfoRenderProps

typescript

Sub-Components

Reusable sub-components for composing custom controls via renderControls.

CloseButton

Default X close button.

tsx

Counter

Image counter pill showing "1 / 3".

tsx

FullscreenButton

Fullscreen toggle button (Maximize/Minimize icon).

tsx

SoundButton

Mute/unmute toggle button for video slides (Volume2/VolumeX icon). Included automatically in renderControls from useVideoSlideRenderer. For standalone use inside custom controls, access sound state via useSoundState.

tsx

Hooks

useVideoSlideRenderer

Hook for opt-in video support. Returns renderSlide, renderControls, and SoundProvider — wrap the overlay in SoundProvider and pass the render functions.

typescript

useFullscreen

Moved
useFullscreen was removed from @reelkit/react-lightbox. Import it from @reelkit/react instead.

Hook for managing fullscreen state with cross-browser support.

tsx

Transitions

Pass any TransitionTransformFn via the transitionFn prop. Importing only the transition you use lets the bundler tree-shake the rest. Defaults to slideTransition when omitted.

FunctionFromDescription
slideTransition@reelkit/react-lightboxStandard horizontal slide (default)
lightboxFadeTransition@reelkit/react-lightboxCrossfade between images
flipTransition@reelkit/react-lightbox3D card flip effect
lightboxZoomTransition@reelkit/react-lightboxZoom in from smaller to normal size
tsx

Custom Transition Function

Author your own TransitionTransformFn and pass it via transitionFn. The signature mirrors core slider transitions.

tsx

CSS Classes

All UI elements use plain CSS classes (not CSS modules) that can be targeted with higher-specificity selectors in a stylesheet loaded after @reelkit/react-lightbox/styles.css. For color, size, and z-index changes, prefer the CSS custom properties documented in the Theming section below.

ClassComponentDescription
.rk-lightbox-overlayOverlayRoot container (full-screen backdrop)
.rk-lightbox-spinnerOverlayDefault loading spinner
.rk-lightbox-img-errorOverlayError state container (broken image/video)
.rk-lightbox-img-error-textOverlayError state text label
.rk-lightbox-swipe-hintOverlayMobile swipe hint
.rk-lightbox-controls-leftControlsTop-left controls container
.rk-lightbox-btnControlsControl buttons (fullscreen, etc.)
.rk-lightbox-closeControlsClose button
.rk-lightbox-counterControlsImage counter chip
.rk-lightbox-navNavigationNavigation arrows (both)
.rk-lightbox-nav-prevNavigationPrevious arrow
.rk-lightbox-nav-nextNavigationNext arrow
.rk-lightbox-infoInfoTitle/description container
.rk-lightbox-titleInfoImage title
.rk-lightbox-descriptionInfoImage description
.rk-lightbox-slideSlideSlide container
.rk-lightbox-imgSlideImage element
.rk-lightbox-video-containerVideoSlideVideo slide container (opt-in)
.rk-lightbox-video-elementVideoSlideVideo element (opt-in)
.rk-lightbox-video-posterVideoSlideVideo poster image (opt-in)

Theming

Every color, size, z-index, and transition lives in a CSS custom property. Override one or many at :root (or any ancestor of the lightbox) to retheme without touching component source.

TokenDefaultControls
--rk-lightbox-overlay-bg#000Full-screen backdrop color
--rk-lightbox-overlay-z9999Overlay z-index
--rk-lightbox-top-shade-height80pxTop gradient scrim height
--rk-lightbox-top-shade-bglinear-gradient(rgba(0,0,0,0.6), transparent)Top gradient scrim color
--rk-lightbox-edge-padding16pxEdge inset for close / nav / top-left controls
--rk-lightbox-controls-gap12pxGap between top-left controls
--rk-lightbox-transition0.2sButton hover transition duration
--rk-lightbox-blur8pxBackdrop blur radius for buttons / chips
--rk-lightbox-btn-bgrgba(0, 0, 0, 0.5)Default background for close, nav, small buttons
--rk-lightbox-btn-bg-hoverrgba(255, 255, 255, 0.2)Hover background for close, nav, small buttons
--rk-lightbox-btn-fg#fffIcon color for close, nav, small buttons
--rk-lightbox-btn-size36pxSmall button size (fullscreen toggle, etc.)
--rk-lightbox-close-size40pxClose button size
--rk-lightbox-nav-size48pxPrev/next arrow size
--rk-lightbox-nav-opacity0.7Idle opacity of prev/next arrows
--rk-lightbox-counter-fg#fffCounter text color
--rk-lightbox-counter-bgrgba(0, 0, 0, 0.5)Counter chip background
--rk-lightbox-counter-size14pxCounter font size
--rk-lightbox-counter-padding6px 12pxCounter chip padding
--rk-lightbox-counter-radius20pxCounter chip border-radius
--rk-lightbox-spinner-size28pxDefault spinner width/height
--rk-lightbox-spinner-trackrgba(255, 255, 255, 0.2)Spinner track color
--rk-lightbox-spinner-fg#fffSpinner indicator color
--rk-lightbox-spinner-duration0.8sSpinner rotation duration
--rk-lightbox-error-fgrgba(255, 255, 255, 0.4)Error icon + text color
--rk-lightbox-error-text-size13pxError message font size
--rk-lightbox-info-bglinear-gradient(transparent, rgba(0,0,0,0.8))Caption scrim gradient
--rk-lightbox-info-padding24pxCaption inner padding
--rk-lightbox-title-size18pxTitle font size
--rk-lightbox-description-size14pxDescription font size
--rk-lightbox-info-fg#fffCaption text color
--rk-lightbox-hint-fgrgba(255, 255, 255, 0.5)Swipe hint text color
--rk-lightbox-hint-bgrgba(0, 0, 0, 0.3)Swipe hint chip background
--rk-lightbox-hint-duration3sSwipe hint fade-in/out total duration
--rk-lightbox-video-bg#000Letterbox background behind <video>

Drop the snippet below into a stylesheet loaded after @reelkit/react-lightbox/styles.css.

css

Accessibility

The overlay root is a modal dialog (role="dialog", aria-modal="true"). Set ariaLabel to change the screen-reader announcement; it defaults to "Image gallery". Each slide carries role="group", aria-roledescription="slide", and aria-label="Image N of M".

The lightbox captures focus on open and returns it to the trigger on close. Tab and Shift+Tab cycle through focusable elements inside; focus that escapes (click outside, programmatic focus) gets pulled back. Implemented with captureFocusForReturn and createFocusTrap from @reelkit/core.

Keyboard Shortcuts

KeyAction
ArrowLeftPrevious image
ArrowRightNext image
EscapeClose lightbox (or exit fullscreen if active)