Image gallery
A compact grid of returned images that opens each one in a shared lightbox.
Installation
npx shadcn@latest add "@assistant-ui/elements-image-gallery"First time? Set up a runtime
Runtime components read their state from an assistant-ui runtime. Add one to an existing project:
npx assistant-ui@latest initThen wrap your app in a runtime provider:
import { AssistantRuntimeProvider } from "@assistant-ui/react";
import { useChatRuntime, AssistantChatTransport } from "@assistant-ui/ai-sdk";
export default function App() {
const runtime = useChatRuntime({
transport: new AssistantChatTransport({ api: "/api/chat" }),
});
return (
<AssistantRuntimeProvider runtime={runtime}>
{/* your components */}
</AssistantRuntimeProvider>
);
}The installation guide covers new projects, templates, and API routes.
npx shadcn@latest add "@assistant-ui/elements-image-gallery"Props-driven: no runtime or provider required.
Image gallery groups several images a tool returned, such as search results or generated variants, into a compact grid without making the transcript heavy.
Getting started
A backend tool can return its finished images as { images }. Its render function passes that result straight to ImageGallery, so a later tool result creates a separate gallery in the transcript.
Render the tool result
"use client";
import {
defineToolkit,
type ToolCallMessagePartComponent,
} from "@assistant-ui/react";
import {
ImageGallery,
type GalleryImage,
} from "@/components/assistant-ui/elements/image-gallery";
type ImageSearchResult = { images: GalleryImage[] };
const ImageSearchToolUI: ToolCallMessagePartComponent<
{ query: string },
ImageSearchResult
> = ({ result }) => <ImageGallery images={result?.images ?? []} />;
export const toolkit = defineToolkit({
show_image_results: {
type: "backend",
render: ImageSearchToolUI,
},
});Render the gallery with images from your own search or generation request. onOpen is useful for lightweight analytics or for synchronizing a nearby detail panel.
import { ImageGallery, type GalleryImage } from "@/components/assistant-ui/elements/image-gallery";
const images: GalleryImage[] = [
{
id: "redwood",
src: "/results/redwood.jpg",
alt: "Sunlight through a redwood grove",
caption: "Generated landscape, variation 1",
},
];
export function Results() {
return <ImageGallery images={images} onOpen={(id) => console.log(id)} />;
}Anatomy
<div data-slot="image-gallery">
<button aria-label="Open image: Sunlight through a redwood grove">
<img loading="lazy" />
</button>
<div role="dialog" aria-modal="true">
<img />
<div>Caption, source, counter, and image controls</div>
</div>
</div>The grid uses two columns and grows to three when its container has room. It shows six images by default. When there are more, the final visible tile reads +N and opens at that image rather than hiding the rest of the gallery. The dialog keeps its place with previous and next controls, ArrowLeft and ArrowRight, and Escape.
Examples
Show an overflow tile
Set maxVisible when the surrounding layout needs a smaller grid. The final visible tile remains the next image in order.
<ImageGallery images={images} maxVisible={3} />Link image sources
An image can carry a caption and source. The source becomes an external link only for a safe http, https, mailto, or relative URL.
<ImageGallery
images={[
{
id: "river",
src: "/results/river.jpg",
alt: "A river seen from above",
caption: "Reference photograph",
source: {
label: "National Park Service",
url: "https://www.nps.gov/",
},
},
]}
/>API reference
Tool result
| Field | Type | Description |
|---|---|---|
result.images | GalleryImage[] | The tool result passed to the gallery after the backend call completes. |
GalleryImage.id | string | Stable image identifier reported to onOpen. |
GalleryImage.src | string | Image URL or data URI. |
GalleryImage.alt | string | Accessible image description and tile label. |
GalleryImage.caption | string | Optional text in the lightbox caption row. |
GalleryImage.source | { label?, url? } | Optional source label, linked only when its URL is safe. |
ImageGallery
| Prop | Type | Default | Description |
|---|---|---|---|
images | GalleryImage[] | required | Images in grid and lightbox order. An empty list renders nothing. |
maxVisible | number | 6 | Number of tiles before the final tile displays the remaining count. |
onOpen | (id: string) => void | Receives the opened image id. | |
className | string | Merged onto the gallery root. |
All other div props are forwarded to the root.