Lays out an image collection as an even grid, masonry columns or justified rows, opens items in the Lightbox, and has an edit mode for listings and gallery blocks: reorder by drag or keyboard (with a Move menu as the non-drag alternative), remove, caption and add.
Installation
The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";
Usage
import { Gallery } from "@vamos-ui/react/media";
<Gallery items={photos} layout="masonry" columns={{ base: 2, md: 3 }} lightbox />Tiles never get backdrop-filter. The hover layer uses --overlay; selection and focus use --ring.
In view mode an empty gallery renders nothing; in edit mode it shows the Add tile.
Examples
Masonry
Items go to the shortest column by their known ratio, so the layout is the same on the server and the client.
Justified rows
Equal-height rows that fill the width exactly; the last row keeps the target height. A proportional flex layout renders before the first measurement.
Captions
below renders a <figcaption>; overlay paints it on a scrim at the bottom of the tile.
Hammam · 75 min ritual Massage suite for two Tea lounge
Edit mode
Drag by the handle or press Space, arrows, Space. Each tile also has a Move menu (WCAG 2.5.7), Remove, and an inline caption. onAdd opens your Media picker.
Responsive columns (team page)
columns follows the gallery's own width (container queries), so it works the same in a sidebar or full width.
Elif Demir, Head of Design Kerem Aydın, Engineering Lead Zeynep Şahin, Product Manager Burak Öztürk, Sales Director Selin Kaya, Customer Success Can Yıldız, Data Analyst
API
Gallery
| Prop | Type | Default |
|---|---|---|
itemsAssets or plain { src, alt, width, height, caption }. width/height drive masonry and justified layouts. | (MediaAsset | MediaSource)[] | — |
layoutEven tiles, columns by ratio, or equal-height rows. | "grid" | "masonry" | "justified" | "grid" |
columnsColumns for grid and masonry, by container width. | number | { base?, sm?, md?, lg? } | { base: 2, sm: 3, lg: 4 } |
aspectTile ratio in the grid layout and edit mode. | ImageAspect | "1/1" |
rowHeightTarget row height in px (justified). | number | 220 |
captionsWhere captions show. | "none" | "below" | "overlay" | "none" |
gap6 / 12 / 20 px between tiles. | "sm" | "md" | "lg" | "md" |
roundedTile corners. | "none" | "ui" | "ui-lg" | "ui" |
lightboxTiles become "Enlarge image: {alt}" buttons that open the Lightbox; pass an object for its options. | boolean | LightboxProps (without items) | false |
sizessizes for every image. Default derived from the column count. | string | — |
loading / skeletonCountSkeleton tiles that keep their ratio. | boolean / number | false / 6 |
labelAccessible name of the list. | string | "Gallery" |
editableEdit mode (grid layout): handle drag + keyboard reorder, Move menu, Remove, caption input, Add tile. | boolean | false |
onReorderNew order of item ids. Without it the items can't be moved. | (ids: string[]) => void | — |
onRemoveShows a Remove button per tile. | (id: string) => void | — |
onCaptionChangeShows an inline caption field (commits on blur / Enter). | (id: string, caption: string) => void | — |
onAdd"Add images" tile (a large drop-style tile when the gallery is empty). | () => void | — |
labelsenlarge, remove, caption, add… (dictionary namespace gallery). | Partial<GalleryLabels> | — |
Layout helpers
| Prop | Type | Default |
|---|---|---|
masonryColumns(ratios, columns)Item indexes per column, shortest column first. | → number[][] | — |
justifyRows(ratios, width, rowHeight, gap?)Flickr-style rows. | → { items, height, justified }[] | — |