Getting StartedComponentsDesign TokensThemingTheme SynthesizerFrameworksAccessibilityUtilitiesServer RenderingBrowser SupportContributingChangelog App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip
ARC UI ARC Radiant Components
v3.2 Docs Components Tokens Synthesizer
Getting StartedFrameworksServer Rendering Design TokensThemingTheme SynthesizerTypographyUtilities All ComponentsAccessibilityBrowser SupportChangelogContributingStats App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip

Lightbox

Full-screen image viewer on the overlay stack: open from a thumbnail, step through a gallery with wrapping prev/next navigation, zoom to 2x with drag-to-pan, and dismiss with Escape or a backdrop click.

Components Lightbox
content interactive
<arc-lightbox>

Overview

Lightbox displays a gallery of images at full screen, above the page behind a blurred backdrop. It shares the overlay infrastructure with Modal and Sheet: keyboard focus is trapped while open, page scroll is locked, Escape and a backdrop click dismiss, and focus returns to the trigger element on close. Open it from a thumbnail with `show(index)`, or set `open` and `index` directly. The gallery is supplied through the `images` property rather than slotted children. Each entry is either a plain `src` string or a `{ src, alt, caption }` object, and the two forms mix freely — captions render below the image and alt text carries through to the rendered `<img>`. A monospace counter in the top bar shows the current position, and prev/next arrow buttons (or the arrow keys) step through the gallery, wrapping at both ends. Zoom is deliberately a single level: press `+`, click the zoom button, or double-click the image to magnify to 2x, then drag to pan around it. Navigating to another image or closing the viewer resets the zoom. The component fires `arc-change` with the new index on every navigation, and `arc-close` is cancelable, so a consumer can veto a dismissal in progress.

Guidelines

When to use

  • Use Lightbox for photo galleries, screenshots, and any image worth inspecting at full size
  • Open it from a visible thumbnail with `show(index)` so the viewer starts on the image the user chose
  • Provide `alt` text for every entry — it also labels the dialog for screen readers
  • Use `caption` for attribution or context that should travel with the image
  • Listen for `arc-change` when something outside the viewer should track the current image

When not to use

  • Do not use Lightbox for non-image content — Modal is the general-purpose overlay
  • Do not open it on page load; a full-screen takeover should always be the user's choice
  • Do not pass tiny thumbnails as the `src` — supply full-resolution sources, since the whole point is a closer look
  • Do not mix it with a second overlay at once; close one surface before opening another

Features

  • Full-screen overlay with backdrop blur, sharing the focus-trap and scroll-lock infrastructure used by Modal and Sheet
  • Accepts plain `src` strings or `{ src, alt, caption }` objects in the same `images` array
  • Prev/next arrow buttons and arrow-key navigation, wrapping at both ends
  • Single-level 2x zoom via the `+`/`-` keys, the zoom button, or a double-click, with drag-to-pan while zoomed
  • Monospace `3 / 12` position counter with a live region for screen readers
  • Caption rendered below the image when an entry provides one
  • Escape and backdrop click dismiss; `arc-close` is cancelable for veto
  • Fires `arc-change` with the new index on `detail.value` on every navigation
  • Focus is trapped while open and restored to the trigger element on close

Preview

Usage

This component requires JavaScript. No pure HTML/CSS version is available — use the Web Component directly or a framework wrapper.

<img id="thumb" src="/photos/valley-thumb.jpg" alt="River valley" />
<arc-lightbox id="viewer"></arc-lightbox>

<script>
  const viewer = document.querySelector('#viewer');
  viewer.images = [
    { src: '/photos/valley.jpg', alt: 'River valley', caption: 'A river valley in evening light' },
    { src: '/photos/slope.jpg', alt: 'Mountain slope' },
    '/photos/canyon.jpg',
  ];
  document.querySelector('#thumb').addEventListener('click', () => viewer.show(0));
</script>
import { Lightbox } from '@arclux/arc-ui-react';
import { useState } from 'react';

const images = [
  { src: '/photos/valley.jpg', alt: 'River valley', caption: 'A river valley in evening light' },
  { src: '/photos/slope.jpg', alt: 'Mountain slope' },
  '/photos/canyon.jpg',
];

function Gallery() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <img src="/photos/valley-thumb.jpg" alt="River valley" onClick={() => setOpen(true)} />
      <Lightbox images={images} open={open} onArcClose={() => setOpen(false)} />
    </>
  );
}
<script setup>
import { ref } from 'vue';
import { Lightbox } from '@arclux/arc-ui-vue';

const open = ref(false);
const images = [
  { src: '/photos/valley.jpg', alt: 'River valley', caption: 'A river valley in evening light' },
  { src: '/photos/slope.jpg', alt: 'Mountain slope' },
  '/photos/canyon.jpg',
];
</script>

<template>
  <img src="/photos/valley-thumb.jpg" alt="River valley" @click="open = true" />
  <Lightbox :images="images" :open="open" @arc-close="open = false" />
</template>
<script>
  import { Lightbox } from '@arclux/arc-ui-svelte';

  let open = $state(false);
  const images = [
    { src: '/photos/valley.jpg', alt: 'River valley', caption: 'A river valley in evening light' },
    { src: '/photos/slope.jpg', alt: 'Mountain slope' },
    '/photos/canyon.jpg',
  ];
</script>

<img src="/photos/valley-thumb.jpg" alt="River valley" onclick={() => open = true} />
<Lightbox {images} {open} on:arc-close={() => open = false} />
import { Component } from '@angular/core';
import { Lightbox } from '@arclux/arc-ui-angular';

@Component({
  imports: [Lightbox],
  template: `
    <img src="/photos/valley-thumb.jpg" alt="River valley" (click)="open = true" />
    <arc-lightbox [images]="images" [open]="open" (arcClose)="open = false"></arc-lightbox>
  `,
})
export class GalleryComponent {
  open = false;
  images = [
    { src: '/photos/valley.jpg', alt: 'River valley', caption: 'A river valley in evening light' },
    { src: '/photos/slope.jpg', alt: 'Mountain slope' },
    '/photos/canyon.jpg',
  ];
}
import { createSignal } from 'solid-js';
import { Lightbox } from '@arclux/arc-ui-solid';

const images = [
  { src: '/photos/valley.jpg', alt: 'River valley', caption: 'A river valley in evening light' },
  { src: '/photos/slope.jpg', alt: 'Mountain slope' },
  '/photos/canyon.jpg',
];

function Gallery() {
  const [open, setOpen] = createSignal(false);

  return (
    <>
      <img src="/photos/valley-thumb.jpg" alt="River valley" onClick={() => setOpen(true)} />
      <Lightbox images={images} open={open()} onArcClose={() => setOpen(false)} />
    </>
  );
}
import { useState } from 'preact/hooks';
import { Lightbox } from '@arclux/arc-ui-preact';

const images = [
  { src: '/photos/valley.jpg', alt: 'River valley', caption: 'A river valley in evening light' },
  { src: '/photos/slope.jpg', alt: 'Mountain slope' },
  '/photos/canyon.jpg',
];

function Gallery() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <img src="/photos/valley-thumb.jpg" alt="River valley" onClick={() => setOpen(true)} />
      <Lightbox images={images} open={open} onArcClose={() => setOpen(false)} />
    </>
  );
}

API

images Array []
The gallery to display. Each entry is either a `src` string or an object of shape `{ src, alt, caption }`; `alt` and `caption` are optional. Set as a property — arrays do not round-trip through attributes.
index number 0
Index of the image currently displayed. Navigation wraps at both ends, so setting it out of range shows the nearest valid image.
open boolean false
Controls the visible state of the viewer. Set to `true` to open at the current `index` and activate the focus trap; set to `false` to close and restore focus to the previously-focused element.

Events

arc-change detail: {value: number, index: number}
Fired when the displayed image changes. `detail.value` is the new index.
arc-close
Fired when the lightbox closes. Cancelable: call `preventDefault()` to veto the close.
arc-open
Fired when the lightbox opens

See Also