Gallery
ProA marketing concepts wall: a balanced headline and lead, an optional tab rail to switch template categories, and a full-bleed fake-masonry of framed preview tiles. Our own Tabs, plus plain CSS columns.
Installation#
Usage#
The preview is yours to explore. Its code comes with a Pro license, paid once and used in every project.
Have a license? Unlock it here
Anatomy#
import {
Gallery,
GalleryHeader,
GalleryTitle,
GalleryDescription,
GalleryMasonry,
GalleryItem,
GalleryImage,
GalleryAccordion,
GalleryAccordionItem,
GalleryAccordionTrigger,
GalleryAccordionPeek,
GalleryAccordionContent,
GalleryAccordionCaption,
GalleryAccordionMedia,
GalleryAccordionImage,
} from "@/components/ui/gallery"
<Gallery>
<GalleryHeader>
<GalleryTitle />
<GalleryDescription />
</GalleryHeader>
<GalleryMasonry>
<GalleryItem>
<GalleryImage />
</GalleryItem>
</GalleryMasonry>
</Gallery>
<GalleryAccordion>
<GalleryAccordionItem>
<GalleryAccordionTrigger peek={<GalleryAccordionPeek />} />
<GalleryAccordionContent>
<GalleryAccordionCaption />
<GalleryAccordionMedia>
<GalleryAccordionImage />
</GalleryAccordionMedia>
</GalleryAccordionContent>
</GalleryAccordionItem>
</GalleryAccordion>Without tabs#
Tabs are an optional composition. Drop the Tabs wrapper and render a single GalleryMasonry directly inside the section for a plain heading-plus-wall layout.
As an accordion#
One more gallery layout: instead of a wall, present the work as a vertical index of collections. Each row previews itself with a peeking thumbnail stack and opens, on click, to a caption and a strip of framed photos that stagger in. It is built on our Accordion (Radix keyboard and ARIA), so only one collection is open at a time. Compose the parts with GalleryAccordion and friends.
density sets the row height: compact (the default, or the nearest DensityProvider) for a dense index, comfortable for a roomier one. The open chapter is controlled with value / defaultValue / onValueChange, and opens on click or keyboard, never hover.
API reference#
Gallery
The full-bleed <section> that provides the styling context and clips the masonry's outer tiles at its edges (overflow-hidden). Forwards all native <section> props; every part accepts className, merged last.
GalleryHeader
The centered lede column for the title, the description and an optional Tabs rail. Forwards all native <div> props.
GalleryTitle
The balanced section heading, on the shared section-heading scale. Forwards all native <h2> props.
GalleryDescription
The muted lead paragraph. Forwards all native <p> props.
GalleryMasonry
The fake-masonry wall: plain CSS columns (2, 3, then 4 across breakpoints), wider than the gutter so the outer columns clip. Retune the count or width via className; forwards all native <div> props.
GalleryItem
One framed tile: a <figure> whose shadow deepens on hover, never a position change. Forwards all native props of the element it renders.
| Prop | Type | Default | Description |
|---|---|---|---|
| action | React.ReactNode | - | Makes the tile a <button> that reveals this label as a centered pill on hover and focus. Pair it with LightboxTrigger, a link or your own onClick; the accessible name comes from the image alt. |
| asChild | boolean | false | Merge the tile styles onto your single child (a link, a LightboxTrigger). Ignored when action is set. |
GalleryImage
The preview image, a plain lazy-loaded, non-draggable <img> that fills its tile. It has no default ratio: pass one per tile (aspect-[4/5]) or real width and height. Forwards all native <img> props.
| Prop | Type | Default | Description |
|---|---|---|---|
| alt | string | "" | Decorative by default; pass a real alt when the image carries meaning. |
GalleryAccordion
The accordion layout's root, a single, collapsible Radix Accordion.Root: one collection open at a time, opened on click or keyboard, never hover.
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | - | The open collection (controlled). Pair with onValueChange. |
| defaultValue | string | - | The collection open on mount (uncontrolled). None open when omitted. |
| onValueChange | (value: string) => void | - | Fires when the open collection changes, via click or keyboard. |
| density | "comfortable" | "compact" | "compact" | Row height and panel inset. Falls back to the nearest DensityProvider. |
| size | "md" | "lg" | "md" | The title scale; lg for hero use. |
| disabled | boolean | false | Disables every item. |
| Data attribute | Description |
|---|---|
| data-orientation | Always "vertical". |
GalleryAccordionItem
One collection, Radix Accordion.Item; forwards all its props.
| Prop | Type | Default | Description |
|---|---|---|---|
| value* | string | - | Unique id of the collection, matched by the root's value. |
| disabled | boolean | false | Stops this collection from opening. |
| Data attribute | Description |
|---|---|
| data-state | "open" or "closed". |
| data-disabled | Present when the item is disabled. |
| data-orientation | Always "vertical". |
GalleryAccordionTrigger
The collection row, Radix Accordion.Trigger wrapped in its Header: the title (children) on the left, the peek, count and a turning + toggle on the right. Forwards all Radix Trigger props.
| Prop | Type | Default | Description |
|---|---|---|---|
| children* | React.ReactNode | - | The collection title. |
| tagline | React.ReactNode | - | One-line tagline under the title, always visible and truncated. |
| count | React.ReactNode | - | The collection size, set in tabular numbers; hidden below sm. |
| peek | React.ReactNode | - | A GalleryAccordionPeek (or any node) shown at rest and faded out on open. |
| Data attribute | Description |
|---|---|
| data-state | "open" or "closed". |
| data-disabled | Present when the item is disabled. |
| data-orientation | Always "vertical". |
GalleryAccordionPeek
The overlapping thumbnail stack on a closed row, decorative (aria-hidden) and hidden below sm. Forwards all native <span> props.
| Prop | Type | Default | Description |
|---|---|---|---|
| images* | { src: string; alt?: string }[] | - | Thumbnails to stack. |
| max | number | 3 | How many thumbnails to show. |
GalleryAccordionContent
The panel, Radix Accordion.Content, tweening its height on open and close. className lands on the inner padded column, not the animated wrapper.
| Prop | Type | Default | Description |
|---|---|---|---|
| forceMount | true | - | Keep the panel mounted while closed (Radix). |
| Data attribute | Description |
|---|---|
| data-state | "open" or "closed". |
| data-disabled | Present when the item is disabled. |
| data-orientation | Always "vertical". |
| CSS variable | Description |
|---|---|
| --radix-collapsible-content-height | The measured panel height the open and close tween animates to and from. |
GalleryAccordionCaption
Optional caption above the photo strip; fades and rises in on open. Forwards all native <p> props.
GalleryAccordionMedia
The horizontal photo strip, scrolling on overflow; its children stagger in left to right on open. Forwards all native <div> props.
GalleryAccordionImage
One framed photo on a mat. Renders a <div>, or a <button> when action is set, and forwards the remaining native props; size the tile via className (h-44 w-60).
| Prop | Type | Default | Description |
|---|---|---|---|
| src* | string | - | The photo source. |
| alt | string | "" | Alt text, also the tile's accessible name when action makes it a button. |
| overlay | React.ReactNode | - | A dimmed overlay over the tile, e.g. a +12 signalling more photos behind it. |
| action | React.ReactNode | - | Makes the tile a <button> that reveals this label as a pill on hover and focus. Pair with LightboxTrigger asChild. |
| loading | "lazy" | "eager" | "lazy" | The native <img> loading attribute. |