Showtimes

Pick one session from a venue's schedule by day, with titles, time chips and a ticket count.

Experience · Shares patterns with Slot Picker, Seat Map

≈ 3,252 tokens per use (tool 972 · guidance 220 · typical payload 2,060)How token costs are estimated

Example: Showtimes

What's playing at the Harbor Lights Cinema tonight?

Harbor Lights Cinema

Times are in Chicago time.

October 2026

Poster: a lone fisherman on a foggy pier at dusk
The Long HarborPG-13 · 2 h 18 min
Poster: a woman among apple trees at night
Glass OrchardSubtitledR · 1 h 52 min · French
Poster: two children under hanging paper moons
Paper MoonsPG · 1 h 34 min

Pick a time

When to use

  • The user wants to see what's on and pick a session: films, theater, concerts, classes, tours, restaurant seatings.
  • The agent fetched a venue's schedule with real session ids.

When not to use

  • The agent hasn't fetched the schedule. Never invent titles or times.
  • There's one title with one session. Ask for a yes or no in text.
  • Booking a generic appointment with no titles to choose between. Use a Slot Picker.

How the agent should use it

  • Every title and session comes from a tool result, with its real id.
  • Only include days that have sessions. Mark sold-out sessions with soldOut instead of dropping them, so the user sees the whole schedule.
  • Set defaultDate to the day the user asked about ("tonight" → today).
  • The result is a choice, not a booking. Check availability and confirm the price before booking anything.

Interaction

  • Header: the venue name, then the month of the visible days with previous and next buttons that page the strip a week (7 session days) at a time when there are more than 7. Paging selects the first day of the new page. The venue's time zone is announced to screen readers only.
  • Day strip: a radio group with a roving tabindex. Arrow keys move between all days (across pages), Home and End jump to the ends. Each day shows its weekday (or its label, e.g. "Today") over the date; the selected day is a filled circle. Days without sessions aren't shown.
  • Sessions: every time chip on the day is one radio in a single group spanning all titles, so there's one selection in total. Each is labelled with its context, e.g. "The Long Harbor, 9:00 PM, IMAX, sold out". Sold-out sessions are disabled and struck through; fewLeft adds a small "Few left". Titles with nothing on the selected day are hidden; with none at all it says "Nothing this day".
  • Title rows: the name, then one quiet line with subtitle, up to two tags (tags that repeat a session format, like "IMAX" on IMAX chips, are dropped) and the lowest price ("From $11.50").
  • Posters: image must be an http(s) URL with real alt. Without one, a neutral tile shows the title's initials.
  • Footer: the chosen session ("Glass Orchard · Sun, Oct 11 · 7:15 PM"), a stepper when quantity is set, the total in bold when the session has a price, and Continue (disabled until a session is picked).
  • Formatting: dates, times and prices use Intl with the locale host prop, "en-US" by default, so server and client agree. Times are wall-clock at the venue and never shifted by the viewer's zone.

Installation

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

Usage

app/api/chat/route.ts
import { tool } from "ai"
import { showtimesTool } from "@/components/genui/showtimes.schema"

const tools = {
  // No execute(): the call is completed by the user's choice in the UI.
  [showtimesTool.name]: tool({
    description: showtimesTool.description,
    inputSchema: showtimesTool.inputSchema,
  }),
}
components/message.tsx
import { Showtimes } from "@/components/genui/showtimes"

function ToolPart({ part, addToolResult }) {
  if (part.type !== "tool-pick_showtime") return null

  return (
    <Showtimes
      {...part.input}
      status={part.state === "input-streaming" ? "streaming" : undefined}
      result={part.state === "output-available" ? part.output : undefined}
      onResult={(result) =>
        addToolResult({
          tool: "pick_showtime",
          toolCallId: part.toolCallId,
          output: result,
        })
      }
    />
  )
}

The agent receives one of:

{ action: "select", sessionId: "go-20261011-1915", titleId: "glass-orchard", date: "2026-10-11", time: "19:15", quantity: 2 }
{ action: "dismiss" }

quantity is only present when the quantity prop was set. Nothing is booked; the agent takes it from there.

With LangGraph

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

Restoring from history

Pass the stored result back as result. It opens on the chosen day with the session and count selected, read-only, and never calls onResult again.

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

Schema

PropTypeNotes
venue{ name, timeZone }?Data-bound. Times are local to the venue
days{ date, label? }[]Data-bound. 1–14 dates with sessions, YYYY-MM-DD
titlesTitle[]Data-bound. What's on
currencystring?ISO 4217 code for prices
defaultDatestring?Day to open on. Default: the first
quantity{ min, max, default, label? }?Adds a stepper. label defaults to "Tickets"
submitLabelstring?Verb for the button. Default "Continue"

Title

FieldTypeNotes
idstringData-bound. Returned in the result
namestring"The Long Harbor"
subtitlestring?"PG-13 · 2 h 18 min · English" or "with Maya Ortiz"
image{ src, alt }?http(s) only. Omit for an initials tile
tagsstring[]?Up to 3: "IMAX", "Subtitled"
sessionsSession[]Data-bound. In time order

Session

FieldTypeNotes
idstringData-bound. Returned in the result
datestringYYYY-MM-DD, venue local
timestringHH:mm, venue local
formatstring?"IMAX", "3D", "Relaxed"
soldOutboolean?Disabled and struck through
fewLeftboolean?Adds "Few left"
pricenumber?Per ticket, in currency

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

Source

On this page