Overlays
Lightbox
A full-screen image viewer — click a thumbnail, see the picture, move through the set.
Import
import { Lightbox } from '@the_viveksingh/vivek-ui'A gallery
Built on the same dialog core as Modal: focus trapped and returned, the page inert, scroll locked, Escape and backdrop click to close. The dialog is named with the position ("Landscapes, 2 of 5") and the counter is a live region. Arrows wrap, Home/End jump, a horizontal swipe moves, thumbnails carry aria-current. alt is required: the image is the content.
Click a photo. Arrows or swipe move through the set, Home/End jump, Escape closes and returns focus to the thumbnail you came from.
<Lightbox
label="Landscapes"
items={[
{ src: '/photos/ridge.jpg', thumbnail: '/photos/ridge-s.jpg', alt: 'Snow-covered ridge at dawn', caption: 'Dawn on the ridge' },
{ src: '/photos/pines.jpg', thumbnail: '/photos/pines-s.jpg', alt: 'Fog in a pine forest' },
{ src: '/photos/lake.jpg', thumbnail: '/photos/lake-s.jpg', alt: 'A still lake at golden hour' },
]}
open={open}
onOpenChange={setOpen}
index={index}
onIndexChange={setIndex}
/>One image, no wrap
A single image shows no arrows or thumbnails. With more than one and loop={false}, the arrows at either end are announced aria-disabled instead of vanishing, so focus never jumps. thumbnails={false} hides the strip; closeOnOverlayClick={false} keeps a backdrop tap from closing.
Click a photo. Arrows or swipe move through the set, Home/End jump, Escape closes and returns focus to the thumbnail you came from.
<Lightbox
items={[{ src: '/diagrams/architecture.png', alt: 'System architecture diagram' }]}
defaultOpen
onOpenChange={(open) => !open && router.back()}
/>
<Lightbox items={steps} loop={false} thumbnails={false} open={open} onOpenChange={setOpen} />Props
Generated from the package's own type declarations, so this table cannot drift from the code.
| Prop | Type | Default | Description |
|---|---|---|---|
items | LightboxItem[] | — | — |
open | boolean | — | — |
defaultOpen | boolean | — | — |
onOpenChange | (open: boolean) => void | — | — |
index | number | — | Controlled index of the shown image. |
defaultIndex | number | — | — |
onIndexChange | (index: number) => void | — | — |
loop | boolean | — | Next after the last wraps to the first. Default `true`. |
thumbnails | boolean | — | Show the thumbnail strip. Default: when there is more than one image. |
label | string | — | Accessible name of the viewer; the position is appended ("…, 2 of 5"). Default `'Image viewer'`. |
closeOnOverlayClick | boolean | — | Clicking the dark backdrop closes. Default `true`. |
swipeThreshold | number | — | Horizontal drag, in px, that counts as a swipe. Default `48`. |
container | PortalContainer | — | — |
Every remaining prop is spread onto the root element, so all standard HTML and ARIA attributes work. className and style are merged with the library's own, never replaced, and the ref forwards to the root DOM node.
Rendering
Lightbox declares 'use client' because it needs state, effects or event handlers. Importing it into a Server Component creates a client boundary at this component — everything above it stays on the server.