Slide Gallery

A slideshow of photos, design options or deck slides, with an optional pick.

Pattern

≈ 1,689 tokens per use (tool 824 · guidance 303 · typical payload 562)How token costs are estimated

Example: Slide Gallery

Show me photos of the apartment on Rua das Flores

Apartment on Rua das Flores

Three-storey building with a pale tiled facade, iron balconies and a wooden front door

Third floor, no lift. Floor plan (opens in a new tab)

Flores Rentals

When to use

  • The user wants to look through a set of images: listing or trip photos, product shots, design options, generated images.
  • Previewing a short presentation deck slide by slide.
  • The user is choosing between visual options: "which of these photos should I post?", "which logo concept?".

When not to use

  • There's a single image. Put it in the reply.
  • The items are records to compare by name, price or rating. Use an Entity Card.
  • The agent doesn't have real image URLs. It must never invent or guess them.
  • The content is a long document. Use an Article.

How the agent should use it

  • Take every image src from a tool result or the host, never from memory. Only http(s) URLs and data:image/(png|jpeg|webp|svg+xml) load; anything else shows "Image unavailable".
  • Write real alt text that says what the image shows. It's required.
  • Keep captions short, a few words on one line. They support **bold** and [links](https://…); add a credit when the source is known.
  • Use deck slides for deck previews: a headline, up to 6 bullets or one stat, and notes for what the speaker says.
  • Set selection only when the user is choosing, with a specific submitLabel (e.g. "Use this concept") and max when it matters.
  • Never set autoplay unless the user asks for a slideshow.

Interaction

  • Navigate with the prev/next buttons (shown on hover and focus, always on touch screens), a swipe, the thumbnails, or the arrow keys, Home and End once the stage has focus. Moves are announced politely: "Slide 3 of 12: Living room".
  • Expand (the icon button in the header, labelled "Expand") opens a full-screen lightbox with the same controls. Escape or Close returns focus to the Expand button.
  • Speaker notes are the one thing collapsed by default, like in a deck tool. They stay open as you move between slides.
  • Autoplay advances every 5 seconds with a visible pause button. It pauses on hover and focus, and doesn't start for people who prefer reduced motion.
  • Selection: each slide gets a Select toggle and its thumbnail a check mark. The footer counts the picks ("1 selected", or "Pick up to 2" for a limited multiple choice; a single choice's "Pick one" is read to screen readers only). Submit is disabled until one is picked, and max is enforced. "None of these" ends with "None selected".
  • Streaming: slides append as they arrive. The stage shows a placeholder until the first slide is complete, and the counter reads "1 / …" until the last one lands.

Installation

npx shadcn@latest add https://your-site.com/r/slide-gallery.json

Usage

app/api/chat/route.ts
import { tool } from "ai"
import { slideGalleryTool } from "@/components/genui/slide-gallery.schema"

const tools = {
  [slideGalleryTool.name]: tool({
    description: slideGalleryTool.description,
    inputSchema: slideGalleryTool.inputSchema,
  }),
}

With selection: "none" the gallery is display-only, so give the tool an execute that returns immediately. With "single" or "multiple", the agent receives one of:

{ action: "select", slideIds: ["leaf"] } // in slide order
{ action: "dismiss" } // "None of these"

With LangGraph

Push it from a graph node with ui.push({ name: "show_gallery", props: { toolCallId, ...args } }, { message }), and render the thread's UI messages with the Renderer.

Restoring from history

When a conversation is reloaded, pass the stored result back as result. The gallery restores the pick (check marks and the footer) read-only and never calls onResult again, so a choice can't be sent twice. With the AI SDK, that's the tool call's output:

<SlideGallery
  {...part.input}
  result={part.state === "output-available" ? part.output : undefined}
/>

Schema

PropTypeNotes
titlestring?e.g. "Apartment on Rua das Flores"
aspect"16:9" | "4:3" | "1:1" | "3:4"Default 16:9 for decks, 4:3 for images. Images are letterboxed, never cropped
selection"none" | "single" | "multiple"Default "none" (display-only)
maxnumber?Most picks with "multiple"
submitLabelstring?Submit button text when selecting
startIndexnumber?Zero-based slide to open on
autoplayboolean5 s per slide. Default false
slidesSlide[]1–30 slides, below

An image slide is { type: "image", id, src, alt, caption?, credit? }. src and credit are data-bound.

A deck slide is { type: "deck", id, title, subtitle?, bullets?, notes?, stat? }, with up to 6 bullets and stat as { value, label }.

Host props: status (streaming, ready, selected, dismissed), onResult, result and className.

Source

On this page