Masonry Caption Gallery
A masonry gallery built with CSS multi-column layout (columns-2 md:columns-3), so every photo keeps its own natural height instead of being cropped into a uniform grid. Each tile is captioned with its subject and place. Clicking any photo opens a drawer that slides in from the right over a semi-transparent backdrop, while the gallery wall stays visible and dimmed behind it.
Docs
Installation
A real shadcn registry command, not a copy-paste stand-in: it fetches this block plus its media-slot dependencies and any missing npm packages, and installs them straight into your project.
npx shadcn add https://staaarter.com/r/masonry-caption-gallery.jsonPrefer not to use the CLI? Copy the source from the Code toggle above into src/components/blocks/gallery/gallery24.tsx instead.
Usage
The file also exports gallery24Demo, the exact props behind the preview above. Spread it to get a working section in one line, then replace it with your own data.
import { Gallery24, gallery24Demo } from "@/components/blocks/gallery/gallery24"; export default function Page() { return <Gallery24 {...gallery24Demo} />; }
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| heading | string | "Field Archive" | Section heading. |
| description | string | undefined | Supporting copy under the heading; omitted entirely when unset. |
| photos | MasonryPhoto[] | none | Photos laid out in CSS columns; each entry's `aspect` sets its own natural height. |
| className | string | undefined | Extra classes for the outer section element. |
Types
interface MasonryPhoto { image?: { src: string; alt: string }; subject: string; place: string; aspect: "square" | "portrait" | "wide" | "tall"; }
Behavior notes
- The masonry layout is plain CSS multi-column (`columns-2 md:columns-3`, each tile `break-inside-avoid mb-4`), not a JS masonry library - this repo doesn't ship one, and the pattern matches other masonry blocks already in this codebase (e.g. Careers' studio-photos block).
- Real client-side state: `isOpen` (boolean) drives a fixed, right-anchored drawer via a CSS `translate-x-full` -> `translate-x-0` transition, alongside a separate backdrop `div` that fades its opacity in/out and toggles `pointer-events` so it's inert while hidden.
- Both Escape (a keydown listener registered in useEffect only while the drawer is open) and a click on the backdrop close the drawer; the backdrop is a non-focusable `aria-hidden` element, Escape and the drawer's own close button remain the accessible ways to dismiss it.
- `activeIndex` (number, which photo the drawer is showing) is deliberately separate from `isOpen` and only ever changes when a tile is clicked, never reset on close, so the drawer keeps showing the last-opened photo while it slides shut instead of the panel going blank mid-animation.
- The gallery wall itself is never blurred or unmounted while the drawer is open, only dimmed by the backdrop sitting above it - it stays visible, matching the brief.
- The photo caption gradient (from-black/75) and the backdrop scrim (bg-black/50) are literal colors, not semantic tokens - both are the sanctioned exceptions for a photo-caption legibility gradient and a modal/drawer backdrop, not a general styling choice.
- "use client" component, so its demo props live in the sibling gallery24.demo.tsx file per this repo's client/demo-file-split rule, not in gallery24.tsx itself.
More Gallery Blocks
View all →Plan Chest Sheet Stack
Ruled plan-chest drawer index that opens into a real stack viewer with a lift-and-rotate top sheet.
Wall Scale Viewer
Print grid with a wall-mockup viewer that scales the piece as you switch between size options.
Archive Record Cards
Text-first archive index that opens into a real 3D flip card of front image and back registrar notes.
Loupe Surface Studies
Square material/texture studies that open into a viewer with a real draggable magnifying loupe.
Paired Hang Compare
Two-to-a-bay staggered hang whose viewer can split into two real panes to compare a second work.
Dark Room Fade Viewer
Inverted low-light hang that opens into a chromeless viewer, the work fading up like a dimmer lamp.