API reference

Props, data attributes, and CSS variables for every Lightbox part. Tables are generated from package TypeScript + JSDoc.

Each part accepts native element props for its default host (via Base UI render where noted). Custom props are listed below. Guides: Composition, View transitions, Gestures.

By concern

Root

Groups all parts of the lightbox and owns open state, active index, view-transition morph, scroll locking, and the active-zoom bridge. Pass handle from Lightbox.createHandle() for imperative control and detached Triggers. Prefer onOpenChangeComplete for post-motion work; use scrollTriggerIntoView so close morphs land on-screen when the page scrolled while open.

Props

Prop
Type
Default
Expand

Trigger

Opens the lightbox at a given index and is the morph source (view transitions on by default). Carries the Base UI dialog-trigger disclosure semantics: aria-haspopup="dialog", aria-controls pointing at the dialog while open, and aria-expanded set only on the trigger that opened it. Pass handle + id to use outside Root or for handle.open(..., { triggerId }). Prefer render-prop children to attach imageRef / morphRef.

Props

Prop
Type
Default
Expand

Data attributes

Attribute
Description
data-ramka-trigger

Always present on the trigger element.

data-popup-open

Present when the corresponding lightbox is open.

data-active

Present when this trigger’s index is the active item.

data-morph-target

Present on the resolved morph element while it is the open/close morph source: the trigger root by default, or the node designated via morphRef when attached. Style hide/opacity against this attribute directly — do not assume it lives on the Trigger button.

data-crossfade

Reflects the crossfade prop: open | close | both.

Portal

Portals Backdrop and Content into a host element (default: document.body). Pass container / keepMounted here. keepMounted parks Backdrop+Content while closed (inert, hidden). When using keepMounted, style z-index on the Portal host yourself (Base UI). Prefer isolation: isolate on the app layout root.

Props

Prop
Type
Default
Expand

Data attributes

Attribute
Description
data-ramka-portal

Always present on the portal host element.

Content

Dialog surface (role="dialog", aria-modal). Provide an accessible name via aria-label or aria-labelledby (required by the WAI-ARIA dialog pattern; the library warns in development if it is missing). Place inside Lightbox.Portal. Owns focus trap, Escape, and pull-to-dismiss. When Lightbox.Stage is mounted, gallery nav (arrows/Home/End), zoom shortcuts (⌘/+/-), pinch/ctrl+wheel zoom, and touch/wheel pull are scoped to Stage (and Zoom pan uses Stage as viewport); otherwise Content itself is the stage. Keyboard pan vs navigate depends on whether the active Zoom is above 1×.

Props

Prop
Type
Default
Expand

Data attributes

Attribute
Description
data-ramka-content

Always present on the dialog surface.

data-open

Present while the lightbox is open.

data-closed

Present while the lightbox is closed (still rendered).

data-pulling

Present while a pull-to-dismiss drag is in progress.

data-pull-snapping

Present while a cancelled pull springs back to rest. data-pulling is dropped on release so chrome can transition; this latch keeps pull-only layout (overflow, shell hide) until the item is parked.

data-pull-dismissing

Present while the dismiss animation runs after crossing the threshold.

data-zooming

Present during an active pinch/zoom gesture (blocks pull-to-dismiss).

data-zoomed

Present when content zoom is greater than 1× (held through zoom-out animation).

CSS variables

Variable
Type
Description
--lightbox-pull-progress

0 at rest → 1 at the dismiss threshold. Drive backdrop/content opacity from this.

--lightbox-pull-snap-duration

Duration of the pull-to-dismiss snap-back, published only while the cancelled pull springs back to rest. Reference it in your transition so progress-derived visuals stay in lockstep with the item's spring, e.g. transition: opacity var(--lightbox-pull-snap-duration, 300ms) var(--lightbox-pull-snap-easing, ease).

--lightbox-pull-snap-easing

Easing of the pull-to-dismiss snap-back (a velocity-aware spring, published only during the spring-back). Pair with --lightbox-pull-snap-duration so backdrop/chrome fades match the item's snap-back exactly.

--lightbox-zoom-progress

0 at 1× → 1 once zoom has risen by 1× above min (e.g. 2× when min is 1). Written by the active Lightbox.Zoom from the *visual* scale (live WAAPI transform while a discrete zoom animates; React zoom otherwise). Cleared when zoom returns to rest. Drive sibling dim/blur from this, e.g. filter: opacity(calc(1 - var(--lightbox-zoom-progress, 0))) blur(calc(var(--lightbox-zoom-progress, 0) * 6px)).

Stage

Optional media interaction surface inside Content. Scopes touch and trackpad wheel pull-to-dismiss, Zoom pan viewport geometry, arrow/Home/End gallery navigation, zoom shortcuts (⌘/+/-), and pinch/ctrl+wheel zoom to the media pane. Interactive controls inside Stage keep their press (Close, Prev/Next, etc.). Place side panels / threads as siblings of Stage under Content. When omitted, Content itself is the stage. Prefer render-prop children to attach morphRef when the open/close morph should capture this surface (or a descendant) instead of the active item.

Props

Prop
Type
Default
Expand

Data attributes

Attribute
Description
data-ramka-stage

Always present on the media interaction stage.

Backdrop

Optional scrim (place inside Lightbox.Portal, typically beside Content). Click closes the lightbox. Tracks pull-to-dismiss progress.

Props

Prop
Type
Default
Expand

Data attributes

Attribute
Description
data-ramka-backdrop

Always present on the backdrop element.

data-open

Present while the lightbox is open.

data-closed

Present while the lightbox is closed (still rendered).

data-pulling

Present while pull-to-dismiss is active (mirrors Content).

data-pull-snapping

Present while a cancelled pull springs back (mirrors Content).

CSS variables

Variable
Type
Description
--lightbox-pull-progress

Same progress variable as Content during pull-to-dismiss.

--lightbox-pull-snap-duration

Same snap-back duration variable as Content during pull-to-dismiss.

--lightbox-pull-snap-easing

Same snap-back easing variable as Content during pull-to-dismiss.

Close

Button that closes the lightbox. Defaults to aria-label="Close".

Props

Prop
Type
Default
Expand

Data attributes

Attribute
Description
data-ramka-close

Always present on the close button.

Item

A single lightbox item. Registers captions and morph/placeholder refs. ARIA adapts automatically: it is a tabpanel wired (aria-labelledby / aria-controls) to its Lightbox.Thumbnail tab when a Lightbox.ThumbnailGroup is present, otherwise a carousel slide (role="group", aria-roledescription="slide", labelled "N of total"). Prefer nesting Lightbox.Media (sized morph + placeholder host) around the destination <img>/<video>; imageRef / morphRef remain escape hatches. Typically nested inside Slide. Outside Slides, every item stays mounted; inside Slides, `preload` gates contents.

Props

Prop
Type
Default
Expand

Data attributes

Attribute
Description
data-ramka-item

Always present on the item element.

data-active

Present when this item is the active index.

data-index

The item index as a string.

data-skip-fade

Transient during view-transition open — suppress consumer entrance fades on the destination item.

Media

Sized destination media host — morph target and placeholder canvas container. Structural props: width/height (fit-box, same idea as Next.js Image); display:grid plus a scoped <style> so direct img/video fill the box (HTML dimension attrs cannot pin intrinsic size). Cosmetics (radius, colors, object-fit) stay consumer-owned. Prefer Zoom > Media > img|video (Zoom is a size container for Media’s cqw/cqh fit-box; put resting chrome insets on Slide padding). Auto-discovers the primary <img> (or video poster) for decode / thumbnail bridging.

Props

Prop
Type
Default
Expand

Data attributes

Attribute
Description
data-ramka-media

Always present on the media host.

data-placeholder

Present while the open-morph placeholder canvas is bridging.

data-width

Present when a structural fit-box width is resolved (prop or img dims).

data-height

Present when a structural fit-box height is resolved (prop or img dims).

Slides

Default layout: horizontal snap carousel wired to the active index. Exposes the WAI-ARIA carousel container (role="group", aria-roledescription="carousel") — give it a label via aria-label / aria-labelledby. Gates Item contents via `preload`; put Slide → Item → Zoom → Media inside. Consumer CSS sizes each Slide snap box (e.g. flex 0 0 100% for full-bleed); index geometry measures offsetLeft/offsetWidth. While the user is flinging, navigation is locked so pull-to-dismiss and zoom chrome do not fight the scroll.

Props

Prop
Type
Default
Expand

Data attributes

Attribute
Description
data-ramka-slides

Always present on the slides scrollport.

data-active-index

Current active index.

data-direction

forward or backward.

data-orientation

Always horizontal.

Slide

One snap-aligned slide box inside Slides. Snap alignment (`scroll-snap-align`, `scroll-snap-stop`) is built in; slide width (full-bleed, aspect-sized cards, …) is consumer CSS — set `flex` / `width` / `min-width` via className or style. Place a Lightbox.Item (and typically Zoom → Media) inside. Prefer putting resting chrome / safe-area insets as padding on Slide (not Zoom) so Item/Zoom fill the content box and zoomed media can paint into the pad under chrome.

Data attributes

Attribute
Description
data-ramka-slide

Always present on the slide element.

Previous

Navigate to the previous item. Disabled at the start when loop is false.

Props

Prop
Type
Default
Expand

Data attributes

Attribute
Description
data-ramka-previous

Always present on the previous button.

data-disabled

Present when navigation is unavailable.

Next

Navigate to the next item. Disabled at the end when loop is false.

Props

Prop
Type
Default
Expand

Data attributes

Attribute
Description
data-ramka-next

Always present on the next button.

data-disabled

Present when navigation is unavailable.

Counter

Shows the active position (e.g. "1 / 12") with an aria-live region.

Props

Prop
Type
Default
Expand

Data attributes

Attribute
Description
data-ramka-counter

Always present on the counter element.

Caption

Renders the active item’s caption from the Item caption registry.

Props

Prop
Type
Default
Expand

Data attributes

Attribute
Description
data-ramka-caption

Always present on the caption element.

data-has-caption

Present when the active item has a caption.

ThumbnailGroup

Accessible tablist of thumbnails with arrow / Home / End keyboard support.

Props

Prop
Type
Default
Expand

Data attributes

Attribute
Description
data-ramka-thumbnail-group

Always present on the thumbnail group (tablist).

data-focus-within

Present when focus is inside the group.

Thumbnail

A single thumbnail tab that activates the given index.

Props

Prop
Type
Default
Expand

Data attributes

Attribute
Description
data-ramka-thumbnail

Always present on the thumbnail button.

data-active

Present when this thumbnail’s index is active.

data-index

The thumbnail index as a string.

ThumbnailStrip

Scroll-linked thumbnail strip root. Always centers the active thumbnail on the midline (Photos-style): owns overflow clip, measured midline track padding (from registered Thumbnail nodes — not role=tab queries), and Slides→track sync via native ScrollTimeline + WAAPI (JS scroll→transform fallback when ScrollTimeline is unavailable). Compose with ThumbnailStripTrack + Thumbnails; optional midline selection chrome is plain consumer markup (strip root is position:relative). Discrete nav (pointer thumb, keyboard, Previous/Next) goes through ThumbnailStrip (DocumentTimeline WAAPI track scrub via scrubOnSelect; element-scoped Slides view transition on pointer select via selectViewTransition — tune with --lightbox-select-vt-duration / --lightbox-select-vt-easing on Slides; optional wrapSelectCommit(commit, slides, index) to arm consumer WAAPI such as an indicator scrub before the scroll jump). Keyboard / Previous / Next keep an instant stage commit while the strip still scrubs. Flex/gap/thumb size remain consumer CSS.

Props

Prop
Type
Default
Expand

Data attributes

Attribute
Description
data-ramka-thumbnail-strip

Always present on the thumbnail strip root.

data-ramka-thumbnail-strip-track

Always present on the scroll-linked tablist track.

data-scrubbing

Present while a discrete-nav scrub animation is in flight.

CSS variables

Variable
Type
Description
--lightbox-thumbnail-strip-travel

End translateX travel for the scroll link (negative px length to center the last thumb — (count - 1) * step when thumbs are uniform). Set on the ThumbnailStripTrack.

--lightbox-select-vt-duration

Duration of the element-scoped Slides view transition on pointer thumb select (selectViewTransition). Set on Slides (or a parent) and use from ::view-transition-group(root) — library starts the transition; CSS owns the look. Default fallback in demos: 0.4s.

--lightbox-select-vt-easing

Easing of the element-scoped Slides view transition on pointer thumb select. Pair with --lightbox-select-vt-duration. Default fallback in demos: cubic-bezier(0.22, 1, 0.36, 1).

ThumbnailStripTrack

Linked tablist track for ThumbnailStrip. A ThumbnailGroup that registers as the ScrollTimeline transform target (same keyboard / ARIA). Parent ThumbnailStrip writes midline padding + travel CSS var and owns the link animation; flex, gap, and thumb sizing are consumer CSS.

Props

Prop
Type
Default
Expand

Zoom

Pinch, wheel, double-tap, and keyboard zoom/pan surface. Fills its host and is a CSS size container (`container-type: size`) for nested Media fit-box units. Does not set overflow (clipping belongs on Content / chrome so zoomed media can escape the resting box). Prefer Zoom > Media > img|video so pan/maxZoom use Media’s content box. Publishes to Root’s active-zoom bridge so ZoomIn/ZoomOut in toolbar chrome can target the active slide.

Props

Prop
Type
Default
Expand

Data attributes

Attribute
Description
data-ramka-zoom

Always present on the zoom container.

data-zoom

Present when zoom > 1.

data-dragging

Present while panning with a pointer.

ZoomIn

Increments zoom. Works inside Zoom, or as global chrome via the active-slide zoom bridge.

Props

Prop
Type
Default
Expand

Data attributes

Attribute
Description
data-ramka-zoom-in

Always present on the zoom-in button.

data-disabled

Present when zoom-in is unavailable.

ZoomOut

Decrements zoom. Works inside Zoom, or as global chrome via the active-slide zoom bridge.

Props

Prop
Type
Default
Expand

Data attributes

Attribute
Description
data-ramka-zoom-out

Always present on the zoom-out button.

data-disabled

Present when zoom-out is unavailable.

Document (view transitions)

While a view-transition morph runs, ramka sets attributes and CSS variables on <html> so you can style ::view-transition-* pseudo-elements. Cleared when the transition finishes.

Data attributes

Attribute
Description
data-ramka-view-transition

Present during a morph. Value is opening or closing.

data-ramka-crossfade

Present while the morph dissolves trigger↔item snapshots (Trigger crossfade is active for this phase). Absent for the default hard-cut.

data-ramka-vt-preset

Present during a morph. Value is the active viewTransition timing preset name (default, snappy, relaxed, spring) — read by the composited morph and available to skin CSS for per-preset styling.

CSS variables

Variable
Type
Description
--lightbox-morph-border-radius-from

Start border-radius for the morph group clip (interpolatable px).

--lightbox-morph-border-radius-to

End border-radius for the morph group clip.

--lightbox-morph-old-opacity

Opacity of the old morph snapshot on the hard-cut path (no document crossfade).

--lightbox-morph-new-opacity

Opacity of the new morph snapshot on the hard-cut path (1 on open, 0 on close).

--lightbox-vt-duration

Morph + root-snapshot duration from the Root's viewTransition timing preset. WRITTEN BY THE LIBRARY in two places — do not set it yourself: onto documentElement during a morph (read it in document-level ::view-transition-* rules, e.g. calc(var(--lightbox-vt-duration) * 0.5) for a derived track), and always onto the Portal host, so skin open/close fades inside the portal can use the preset's clock even when no morph runs (non-VT browsers, reduced motion, low-end fallback), e.g. transition: opacity var(--lightbox-vt-duration, 360ms) ease-out.

--lightbox-vt-easing

Easing for ::view-transition-group(lightbox-morph) and the *open* crossfade dissolve. Written by the library from the viewTransition preset, like --lightbox-vt-duration (during a morph on documentElement, always on the Portal host). Close dissolve uses --lightbox-vt-crossfade-close-easing (a shorter complementary fade, not the morph curve) so the item yields before the size settle.

--lightbox-vt-crossfade-close-easing

Close trigger↔item snapshot dissolve, used while data-ramka-view-transition="closing" and data-ramka-crossfade are set. Modest ease-out on a shorter window that still runs old 1→0 and new 0→1 on the same clock (plus-lighter stays opaque). Written by the library onto documentElement during a morph — do not set it yourself.

--lightbox-vt-root-easing

Easing for the root snapshot cross-fade (::view-transition-old/new(root)). Written by the library from the viewTransition preset, like --lightbox-vt-duration (during a morph on documentElement, always on the Portal host). A good default for skin backdrop/content fades.

Types

Helper types you will see in callbacks and render props (exported from @ramka/react / the Lightbox module):

  • NavigationSource 'trigger' | 'keyboard' | 'thumbnail' | 'button' | 'scroll' | 'imperative'. Second argument to Root onValueChange. Handle open/goTo use 'imperative'; scroll-driven Slides use 'scroll'.
  • LightboxCrossfade 'open' | 'close' | 'both' for Trigger crossfade. See View transitions → crossfade.
  • Render-state types such as LightboxTriggerRenderState and Item render args (active, visible, refs) — documented on Trigger / Item.

Hooks

Optional contexts for nested wrapper components.

useLightboxTriggerContext

Optional context from the enclosing Trigger. Use in nested wrappers (e.g. a shared <TriggerImage>) to attach imageRef / morphRef without threading the render prop.

Props

Prop
Type
Default
Expand

useLightboxItemContext

Optional context from the enclosing Item. Use in nested wrappers to attach imageRef / morphRef or read active/index. Prefer Lightbox.Media for the common morph/placeholder host.

Props

Prop
Type
Default
Expand

useLightboxMediaContext

Optional context from the enclosing Media. Exposes the Media host element for advanced wrappers.

Props

Prop
Type
Default
Expand

useLightboxStageContext

Optional context from the enclosing Stage. Use in nested wrappers to attach morphRef without threading the render prop — the shared View Transition capture destination.

Props

Prop
Type
Default
Expand

Imperative handles

Use Lightbox.createHandle() on Root (and optional detached Triggers). Zoom exposes zoom controls via ref.

LightboxHandle

Imperative handle from Lightbox.createHandle(). Pass to Root (and optional detached Triggers).

Props

Prop
Type
Default
Expand

LightboxZoomRef

Imperative handle from ref on Zoom.

Props

Prop
Type
Default
Expand