Gallery

A masonry / justified / uniform thumbnail grid — a real layout engine plus a zero-CLS lazy-media pipeline, a view-agnostic multi-select model (click · shift-range · marquee · keyboard), a built-in lightbox, FLIP re-layout motion, drag-reorder, and windowed virtualization for large asset libraries.

Betav0.3.0@garn/ui/gallery

Default

Column-packed variable heights (Pinterest) — native `grid-template-rows: masonry` on Safari 26+, a DOM-order computed-span fallback elsewhere.

Layout

Masonry

Column-packed variable heights (Pinterest) — native `grid-template-rows: masonry` on Safari 26+, a DOM-order computed-span fallback elsewhere.

Justified

Flickr / Google-Photos row-fill — each row scales to exactly fill the container width; the last row is left-aligned.

Uniform

An aspect-cropped auto-fill grid (DAM / Instagram) — the cheapest, most common shape.

Columns

A fixed column count (`columns={3}`) with a non-square crop ratio, instead of auto-fill.

Media

Placeholder

Blur-up LQIP placeholders — a tiny data-URI blurs up as the full image decodes (zero CLS).

Broken

A broken source falls back to a muted broken-image glyph without collapsing the tile.

Selection

Selectable

Multi-select — click, ⇧-range, ⌘/Ctrl-toggle, marquee drag, and arrows + Space; controlled via `selectedIds`.

2 selected · click, ⇧-click for a range, ⌘/Ctrl-click to toggle, or drag a box across the tiles. Arrows + Space navigate.

Overlay

Tile metadata in a `Gallery.Overlay` (title + dimensions) that appears on hover / focus / selected.

Motion

Motion

FLIP re-layout — tiles glide between positions when the order changes (shuffle to see it); off under reduced motion.

Reorder

Reorder

Drag-to-reorder — hover a tile for its grip and drag, or focus the grip and use Space + arrows. Powered by the sortable primitive.

Hover a tile for its grip, then drag to reorder (or focus the grip and use Space + arrows). Powered by the sortable primitive.

Virtualization

Virtualized

240 assets, windowed — only the tiles near the scroll viewport are mounted.

240 assets, windowed — only the tiles near the viewport are mounted. Scroll the panel below.

States

Empty

The empty state rendered via the `empty` prop when there are no items.

No assets yet.