Control the lightbox from code
Open the lightbox at a given photo from a button, bind the active photo with v-model:active, close it with the browser Back button, link to a photo with deepLink, and move next and previous with template refs or useLightbox().
There are two ways to control a lightbox from your code:
- A template ref on any ready-made component opens and closes it.
useLightbox()in a child component also moves between photos and reads the current state.
Open a photo from a button
<script setup lang="ts">
import type { GalleryHandle, PhotoItem } from '@lupinum/nuxt-photo/app'
const props = defineProps<{ photos: PhotoItem[] }>()
const album = useTemplateRef<GalleryHandle>('album')
</script>
<template>
<button type="button" :disabled="props.photos.length < 5" @click="album?.open(4)">
Open the fifth photo
</button>
<PhotoAlbum ref="album" :photos="photos" />
</template>Indexes start at 0. openById('canyon') opens a photo by its id, which
stays right when the order changes. Both reject with a RangeError for an
index or ID that does not exist.
Every ready-made component exposes the same handle:
interface GalleryHandle {
open(index?: number): Promise<void>
openById(id: string): Promise<void>
close(): Promise<void>
readonly isOpen: boolean
readonly activeId: string | null
readonly activePhoto: PhotoItem | null
}For an album inside a PhotoGroup, open(index) counts in that album; the
group's handle counts in the group. Photo accepts index 0 or its own ID.
PhotoCarousel also exposes scrollTo(index), next(), and prev() for its
inline track.
Bind the active photo
Use v-model:active on Photo, PhotoAlbum, PhotoGroup, or PhotoCarousel:
<script setup lang="ts">
import type { PhotoItem } from '@lupinum/nuxt-photo/app'
defineProps<{ photos: PhotoItem[] }>()
const active = ref<string | null>(null)
</script>
<template>
<PhotoAlbum v-model:active="active" :photos="photos" />
</template>Enable the lightbox before using the model. Photo and PhotoCarousel need
the lightbox prop; albums and groups enable it by default.
Set an ID to open or navigate. Set null to close. User navigation updates the
value. Unknown IDs are ignored with one development warning per component.
The handle reports activeId and activePhoto as null when closed. For
Photo, the model is its single ID or null.
Control the lightbox from a child component
useLightbox() returns the full controller of the nearest parent provider:
PhotoGroup or LightboxProvider.
<script setup lang="ts">
import { useLightbox } from '@lupinum/nuxt-photo/app'
const lightbox = useLightbox()
</script>
<template>
<div class="gallery-toolbar">
<span v-if="lightbox.isOpen.value">
{{ lightbox.activeIndex.value + 1 }} of {{ lightbox.count.value }}
</span>
<button type="button" @click="lightbox.prev()">Previous</button>
<button type="button" @click="lightbox.next()">Next</button>
</div>
</template><template>
<PhotoGroup :photos="photos">
<GalleryToolbar />
<PhotoAlbum :photos="photos" />
</PhotoGroup>
</template>Call useLightbox() in a component rendered inside the provider, not in the
component that renders the provider.
interface LightboxController {
readonly photos: ComputedRef<readonly PhotoItem[]>
readonly count: ComputedRef<number>
readonly activeId: ComputedRef<string | null>
readonly activeIndex: ComputedRef<number>
readonly activePhoto: ComputedRef<PhotoItem | null>
readonly isOpen: ComputedRef<boolean>
open(index?: number): Promise<void>
openById(id: string): Promise<void>
close(): Promise<void>
next(): void
prev(): void
toggleZoom(): void
}next() and prev() do nothing while the lightbox is closed. Calling
close() twice is safe. The promises settle when the opening or closing
animation has finished.
Close the lightbox with the Back button
The lightbox adds a browser history entry when it opens. Back closes the lightbox and leaves the page where it was: the page does not scroll, the router does not navigate, and route middleware does not run again. Closing with the close button or Escape removes the entry again, so a later Back leaves the page as usual.
This is on by default. Turn it off for one gallery:
<PhotoAlbum :photos="photos" :lightbox="{ history: false }" />Or for the whole app:
export default defineNuxtConfig({
nuxtPhoto: { lightbox: { history: false } },
})When several galleries are on one page, only the open lightbox writes history.
Link to a photo
With deepLink, the URL shows the open photo, so a shared link opens it:
<template>
<PhotoAlbum :photos="photos" :lightbox="{ deepLink: true }" />
</template>- While the lightbox is open, the URL has
?photo=<id>. Moving to another photo replaces the value; it does not add a history entry. - A page that loads with
?photo=<id>opens that photo without the opening animation, also after server rendering. - An ID that is not in this gallery is ignored.
deepLink: 'image'uses?image=<id>instead. Give each gallery on a page its own name, so their links do not interfere.
IDs appear in shared URLs. Use IDs that are stable and contain nothing private.
Every lightbox option and its default is in the lightbox reference.