Timeline

Ordered events with a state each, like shipment tracking, an incident or project milestones.

Pattern

≈ 734 tokens per use (tool 354 · guidance 200 · typical payload 180)How token costs are estimated

Example: Timeline

Where's my Oakline order?

Order #4821 from Oakline Goods

  1. Order placed (Done)
  2. Packed at the Porto warehouse (Done)
  3. Handed to the courier (Done)

    RX 2291 0448 PT

  4. Arrived at the Lisbon hub (Done)
  5. Out for delivery (In progress)
  6. Delivered (Upcoming)By 14:00

When to use

  • The user asks where something is or what happened, and the answer is a sequence of dated events: a shipment, an incident, a project.
  • The order and timing of the events matter, not just the latest one.

When not to use

  • Only the latest event matters. Say it in a sentence.
  • The steps are tasks the user still has to do. Use a Checklist.
  • You don't have the events from a tool. Never invent timestamps.

How the agent should use it

  • List events oldest first, with times copied from the tool result.
  • Mark at most one event current, and the ones after it upcoming.
  • Use failed for the step that broke, then show the recovery as its own event.
  • Keep titles short and put detail in description.

Times

ISO timestamps and dates are formatted with Intl in the viewer's locale and time zone. A timestamp on the same day as the one before it shows only the time, so a same-day incident doesn't repeat its date. Timestamps within a day of now get a hint like "2h ago", computed on the client. Anything that isn't ISO, like "Q1" or "By 14:00", is shown as written.

Installation

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

Usage

The Timeline is display-only, so the tool can return immediately:

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

const tools = {
  [timelineTool.name]: tool({
    description: timelineTool.description,
    inputSchema: timelineTool.inputSchema,
    execute: async () => ({ shown: true }),
  }),
}

Render it through the Renderer under show_timeline, or directly:

<Timeline {...part.input} status={part.state === "input-streaming" ? "streaming" : "ready"} />

With LangGraph

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

Schema

PropTypeNotes
titlestring
events{ id, time, title, description?, state? }[]2–30 events, oldest first. Data-bound. time is ISO or a short label
events[].state"done" | "current" | "upcoming" | "failed"Omit for plain past events
orientation"vertical"Default vertical

Host props: status (streaming or ready) and className.

Source

On this page