# <motion-gallery>

Image gallery with a spring-animated expand/collapse lightbox. Grid layout with
hover scaling on each item. Opens a full-viewport lightbox with prev/next navigation,
keyboard support, and focus trapping.

**Use it for:** a grid of photos or screenshots that people open one at a
time in a large view and step through.

**Avoid it for:** a single image, or images that link to other pages,
because every item becomes a button. To compare two versions of one image,
use `motion-image-compare`. To show one large slide at a time, use
`motion-slider`.

**Accessibility:** the host gets `role="group"` and the label "Image
gallery". Each item gets `role="button"`, `tabindex="0"` and
`aria-haspopup="dialog"`, and opens with Enter or Space. The lightbox has
`role="dialog"` and `aria-modal="true"`. Focus moves to its close button,
Tab stays on the lightbox buttons, the Left and Right arrow keys change
the item, a live region reads the position, and Escape closes it and
returns focus. Each item's label is its `data-caption`, or "Open item 1 of
3" when there is none, and this label replaces the `alt` text, so give
every item a `data-caption`.

**Reduced motion:** the entrance stagger and the hover lift are off, the
backdrop shows at once, and opening, changing and closing items happen
with no animation.

**Common mistakes:** adding items after the gallery is in the page; it
reads its children once, so later items do not open the lightbox. Styling
items with `motion-gallery > img`; each item is moved into a
`motion-hover` wrapper (and into a `motion-stagger` when `stagger` is on),
so use a class on the item instead.

Docs: https://www.motion-components.dev/docs/components/motion-gallery/

## Install

```js
import 'motion-components/motion-gallery'
```

Or without a build step:

```html
<script type="module" src="https://cdn.jsdelivr.net/npm/motion-components@1/dist/motion-gallery.js/+esm"></script>
```

## Example

```html
<motion-gallery columns="3" gap="16" aspect-ratio="4/3">
  <img src="photo-1.jpg" alt="Photo 1" data-caption="Sunset view" />
  <img src="photo-2.jpg" alt="Photo 2" data-caption="Mountain trail" />
  <img src="photo-3.jpg" alt="Photo 3" />
</motion-gallery>
```

## Attributes

| Attribute | Type | Default | Description |
| --- | --- | --- | --- |
| `columns` | `number` | `3` | Number of grid columns. |
| `gap` | `number` | `16` | Grid gap in pixels. |
| `aspect-ratio` | `string` |  | CSS `aspect-ratio` for each item. Unset by default, so items keep their intrinsic ratio. |
| `stagger` | `boolean` | `true` | Stagger the entrance animation. Set `"false"` to disable. Read once on connect. |

## Properties

| Property | Type | Description |
| --- | --- | --- |
| `index` | `number` | Index of the item open in the lightbox, or -1 while it is closed. |

## Methods

| Method | Description |
| --- | --- |
| `open()` | Opens the lightbox on the item at `index`, or moves to it when the lightbox is already open. |
| `close()` | Closes the lightbox. |
| `prev()` | Moves the lightbox to the previous item. Does nothing on the first one or while closed. |
| `next()` | Moves the lightbox to the next item. Does nothing on the last one or while closed. |

## Events

The `motion-*` events bubble and are composed.

| Event | Description |
| --- | --- |
| `name` |  |
| `motion-open` | The lightbox opened. `detail: { index }`. |
| `motion-change` | The lightbox moved to another item. `detail: { index }`. |
| `motion-close` | The lightbox closed. |

## Slots

| Slot | Description |
| --- | --- |
| (default) | Gallery items. Each item should have a unique `data-caption` for the lightbox caption overlay (optional). Items are expected to be images or media elements. `columns`, `gap` and `aspect-ratio` are live. `stagger` is read once, when the entrance animation runs. |
