Timeline
Ordered events with a state each, like shipment tracking, an incident or project milestones.
≈ 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
- Order placed (Done)
- Packed at the Porto warehouse (Done)
- Handed to the courier (Done)
RX 2291 0448 PT
- Arrived at the Lisbon hub (Done)
- Out for delivery (In progress)
- 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 itupcoming. - Use
failedfor 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:
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
| Prop | Type | Notes |
|---|---|---|
title | string | |
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.