Skip to main content

PhotoGroup

Give several photo sections one explicit collection and shared lightbox.

PhotoGroup owns one ordered collection and lightbox. Descendant Photo and PhotoAlbum components register triggers by stable photo ID.

Minimal usage

app/pages/portfolio.vue
<script setup lang="ts">
import type { PhotoItem } from '@lupinum/nuxt-photo/app'

const photos: PhotoItem[] = [
  { id: 'one', src: '/photos/one.jpg', width: 1200, height: 800, alt: 'Coastline' },
  { id: 'two', src: '/photos/two.jpg', width: 800, height: 1200, alt: 'Pine tree' },
]
</script>

<template>
  <PhotoGroup :photos="photos">
    <PhotoAlbum :photos="photos" />
  </PhotoGroup>
</template>

Props

PropTypeDefaultDescription
photosreadonly PhotoItem[]-Required. Canonical collection and order.
validation'throw' | 'drop''throw'Invalid collection policy.
imageAdapterImageAdapterprovided/module defaultImage adapter for the group.
lightboxboolean | ComponenttrueEnable, disable, or replace the lightbox.
transitionLightboxTransitionOption'auto'Lightbox transition configuration.

Events

EventPayloadWhen it fires
invalidPhotosInvalidPhotosEventInvalid entries are found while validation="drop" is set.
vue
<PhotoGroup :photos="photos" validation="drop" @invalid-photos="reportInvalidPhotos">
  <PhotoAlbum :photos="photos" />
</PhotoGroup>

Slots

SlotPropsPurpose
default{ photos, controller }Render group content and access the full controller.

The slot photos value is readonly and keeps the canonical prop order. controller is LightboxProviderController.

Exposed template-ref API

PhotoGroup exposes LightboxHandle:

ts
interface LightboxHandle {
  open(index?: number): Promise<void>
  openById(id: string): Promise<void>
  close(): Promise<void>
  readonly isOpen: boolean
}

Invalid indexes and IDs reject with a namespaced RangeError. close() is idempotent.

Important behavior

  • photos is the only identity and navigation-order source.
  • Every interactive descendant ID must exist in the collection.
  • A descendant becomes inert if its ID is removed while the descendant remains rendered.
  • Competing custom slide renderers for one ID throw during registration.
  • photos and transition are reactive.
  • lightbox is setup-time. A group mounted with lightbox="false" stays inert; remount with a new key to enable it.

Several albums, one navigation order

vue
<PhotoGroup :photos="[...landscapes, ...portraits]">
  <PhotoAlbum :photos="landscapes" />
  <PhotoAlbum :photos="portraits" />
</PhotoGroup>

Changing the visual order does not change next and previous navigation. Change the group photos array to change that order.

Share one lightbox provides the task-based setup. Collections and navigation order explains why the collection is explicit.