Full-screen image viewer. Wraps a group of trigger images and, when one is activated, opens them in a modal dialog with keyboard/swipe navigation, prev/next buttons and dot indicators.
Use Lightbox when clicking a thumbnail should open a full-screen, navigable view of a set of images. It is the current replacement for the deprecated ImageGallery.
Images register themselves with the surrounding Lightbox via the useLightboxImage hook, so any element (custom thumbnail, button, RasterImage) can act as a trigger. There is no @uxf/form twin.
import { Lightbox, useLightboxImage } from "@uxf/ui/lightbox";
import { RasterImage } from "@uxf/ui/raster-image";
const images = [
{ src: "image1.jpg", title: "Image 1" },
{ src: "image2.jpg", title: "Image 2" },
{ src: "image3.jpg", title: "Image 3" },
];
function GalleryImage(props: { src: string; title: string }) {
// useLightboxImage registers the image with the Lightbox context and
// returns the callback that opens the dialog on this image.
const openLightbox = useLightboxImage({ src: props.src, title: props.title });
return (
<button onClick={openLightbox}>
<RasterImage alt="" src={props.src} width={224} />
</button>
);
}
export function Gallery() {
return (
<Lightbox>
<div className="flex gap-2">
{images.map((image) => (
<GalleryImage key={image.src} src={image.src} title={image.title} />
))}
</div>
</Lightbox>
);
}
Lightbox| Prop | Type | Default | Description |
|---|---|---|---|
children |
ReactNode |
— | Required. Trigger content; images register via useLightboxImage. |
isBackdropCloseDisabled |
boolean |
false |
Prevents closing when the backdrop is clicked. |
CloseButtonElement |
FC<LightboxButtonProps> |
built-in | Custom close-button component. |
NextButtonElement |
FC<LightboxButtonProps> |
built-in | Custom next-button component. |
PrevButtonElement |
FC<LightboxButtonProps> |
built-in | Custom prev-button component. |
DialogElement |
FC<LightboxCustomDialogProps> |
built-in | Replaces the entire dialog (see Custom dialog). |
| Export | Signature | Description |
|---|---|---|
useLightboxImage |
(props: LightboxImageProps) => () => void |
Registers an image on mount, unregisters on unmount, and returns a callback that opens the dialog on that image. The primary way to wire triggers. |
useLightbox |
() => { images, imageIndex, registerImage, unregisterImage, openLightbox, onNextImage, onPrevImage, onClose } |
Internal state hook consumed by Lightbox itself; rarely needed directly. |
LightboxImageProps |
{ src: ImageSource; alt?: string; title?: string; className?: string; customContent?: ReactNode } |
Descriptor of a registered image. customContent is overlaid on the image in the dialog. |
LightboxButtonProps |
{ onClick: MouseEventHandler } |
Props passed to custom button components. |
LightboxCustomDialogProps |
{ imageIndex: number; images: LightboxImageProps[]; onClose; onNext; onPrev } |
Props passed to a custom DialogElement. |
Navigation: prev/next buttons and dot indicators render only when more than one image is registered. ArrowLeft/ArrowRight move between images, Escape closes, and horizontal swipe navigates on touch. The index wraps around at both ends.
Body scroll is locked while the dialog is open.
Custom buttons: supply CloseButtonElement / NextButtonElement / PrevButtonElement as components receiving LightboxButtonProps:
import { Lightbox, LightboxButtonProps } from "@uxf/ui/lightbox";
function CustomNextButton(props: LightboxButtonProps) {
return <button onClick={props.onClick}>Next</button>;
}
<Lightbox NextButtonElement={CustomNextButton}>{/* triggers */}</Lightbox>;
Custom dialog: for full control, pass DialogElement. The useLightboxDialog helper (deep import @uxf/ui/lightbox/components/use-lightbox-dialog) wires keyboard handling, swipe and the current image:
import { Lightbox, LightboxCustomDialogProps } from "@uxf/ui/lightbox";
import { useLightboxDialog } from "@uxf/ui/lightbox/components/use-lightbox-dialog";
function CustomDialog(props: LightboxCustomDialogProps) {
const { imageSrc, imageCustomContent, swipableHandlers } = useLightboxDialog({
imageIndex: props.imageIndex,
images: props.images,
onClose: props.onClose,
onNext: props.onNext,
onPrev: props.onPrev,
});
return (
<div {...swipableHandlers}>
<button onClick={props.onClose}>Close</button>
{typeof imageSrc === "string" && <img alt="" src={imageSrc} />}
{imageCustomContent}
<button onClick={props.onPrev}>Previous</button>
<button onClick={props.onNext}>Next</button>
</div>
);
}
<Lightbox DialogElement={CustomDialog}>{/* triggers */}</Lightbox>;
Import the component stylesheet once in your global CSS. The default buttons render an Icon, so its stylesheet is required too:
@import url("@uxf/ui/css/icon.css");
@import url("@uxf/ui/css/lightbox.css");
Also requires the global @uxf/ui token layer, set up once per app — see @uxf/ui setup.