ComponentsTimeline
Timeline
Show events in order with statuses and optional selection.
On this page
Use this component from the local workspace package. Follow the setup guide first. A public npm package and registry are not available yet.
View registry filesImport the component into your page or component file.
import {
Timeline,
type TimelineItemData,
} from "@dethink/components";Try the examples, then open the code to use them in your app. Focus the track and use the arrow keys to move between items.
Events
Dated milestones with complete, current, and upcoming statuses.
Status: Complete Research complete
User needs and interaction model approved.
Status: Current Private beta
First teams using the component in dashboards.
Status: Upcoming General availability
Registry item, docs, and release notes ship.
Show sourceexamples/timeline/basic.tsx
"use client";
import { Timeline, type TimelineItemData } from "@dethink/components";
const milestones: TimelineItemData[] = [
{
id: "research",
title: "Research complete",
description: "User needs and interaction model approved.",
datetime: "2026-01-12T09:00:00Z",
dateLabel: "Jan 12",
status: "complete",
},
{
id: "beta",
title: "Private beta",
description: "First teams using the component in dashboards.",
datetime: "2026-03-18T10:00:00Z",
dateLabel: "Mar 18",
status: "current",
},
{
id: "ga",
title: "General availability",
description: "Registry item, docs, and release notes ship.",
datetime: "2026-05-05T10:00:00Z",
dateLabel: "May 5",
status: "upcoming",
},
];
export function TimelineBasic() {
return <Timeline aria-label="Release milestones" items={milestones} />;
}Progress
progress mode drops the dates for an evenly spaced step sequence — pipelines, wizards, order tracking.
Status: Complete Queued
Waiting for a build slot.
Status: Current Building
Compiling and running checks.
Status: Upcoming Deploying
Rolling out to the edge.
Status: Upcoming Live
Serving production traffic.
Show sourceexamples/timeline/progress.tsx
"use client";
import { Timeline, type TimelineItemData } from "@dethink/components";
const steps: TimelineItemData[] = [
{
id: "queued",
title: "Queued",
description: "Waiting for a build slot.",
status: "complete",
},
{
id: "building",
title: "Building",
description: "Compiling and running checks.",
status: "current",
},
{
id: "deploying",
title: "Deploying",
description: "Rolling out to the edge.",
status: "upcoming",
},
{
id: "live",
title: "Live",
description: "Serving production traffic.",
status: "upcoming",
},
];
export function TimelineProgress() {
return (
<Timeline
aria-label="Deployment progress"
mode="progress"
scale="auto"
layout="stacked"
items={steps}
defaultSelectedId="building"
/>
);
}Flow presentation with reveal
presentation="flow" swaps the pan/zoom viewport for a static document-flow list, and reveal="stagger" with the in-view trigger animates the items in one by one as they scroll into view. Reduced-motion users see everything immediately.
Status: Complete Project kickoff
Scope agreed and delivery squad assembled.
Status: Complete Design review
Flows approved with two accessibility follow-ups.
Status: Current Build sprint
Core screens implemented behind a feature flag.
Status: Upcoming Launch
Flag removed and rollout announced.
Show sourceexamples/timeline/flow-reveal.tsx
"use client";
import { Timeline, type TimelineItemData } from "@dethink/components";
const milestones: TimelineItemData[] = [
{
id: "kickoff",
title: "Project kickoff",
description: "Scope agreed and delivery squad assembled.",
datetime: "2026-02-02T09:00:00Z",
dateLabel: "Feb 2",
status: "complete",
},
{
id: "design",
title: "Design review",
description: "Flows approved with two accessibility follow-ups.",
datetime: "2026-03-09T14:00:00Z",
dateLabel: "Mar 9",
status: "complete",
},
{
id: "build",
title: "Build sprint",
description: "Core screens implemented behind a feature flag.",
datetime: "2026-04-20T10:00:00Z",
dateLabel: "Apr 20",
status: "current",
},
{
id: "launch",
title: "Launch",
description: "Flag removed and rollout announced.",
datetime: "2026-06-01T10:00:00Z",
dateLabel: "Jun 1",
status: "upcoming",
},
];
/**
* presentation="flow" renders the same events data as a static document-flow
* list — no pan/zoom viewport — and reveal="stagger" animates the items in
* one by one as the timeline scrolls into view. Reduced-motion users see
* every item immediately.
*/
export function TimelineFlowReveal() {
return (
<Timeline
aria-label="Project milestones"
items={milestones}
presentation="flow"
reveal="stagger"
revealOptions={{ trigger: "in-view" }}
/>
);
}Streaming reveal
Appending to the items array animates only the new points in — built for live sources like agent runs, deploy logs, or activity feeds.
Status: Complete 12:04:01Run queued
Agent run accepted and scheduled.
Status: Complete 12:04:07Plan drafted
Task broken into three tool calls.
Show sourceexamples/timeline/reveal-streaming.tsx
"use client";
import { useState } from "react";
import { Button, Timeline, type TimelineItemData } from "@dethink/components";
const runEvents: TimelineItemData[] = [
{
id: "queued",
title: "Run queued",
description: "Agent run accepted and scheduled.",
dateLabel: "12:04:01",
status: "complete",
},
{
id: "plan",
title: "Plan drafted",
description: "Task broken into three tool calls.",
dateLabel: "12:04:07",
status: "complete",
},
{
id: "search",
title: "Search executed",
description: "Indexed 42 documents, 6 strong matches.",
dateLabel: "12:04:18",
status: "complete",
},
{
id: "draft",
title: "Draft generated",
description: "Summary produced from the top matches.",
dateLabel: "12:04:31",
status: "current",
},
{
id: "review",
title: "Awaiting review",
description: "Draft handed off for human approval.",
dateLabel: "12:04:32",
status: "upcoming",
},
];
/**
* Growing the items array appends points live: only the new items animate in,
* so a streaming source — an agent run, a deploy log, a support thread — can
* push events onto the timeline one at a time.
*/
export function TimelineRevealStreaming() {
const [count, setCount] = useState(2);
const done = count >= runEvents.length;
return (
<div className="space-y-4">
<div className="flex justify-center gap-2">
<Button
size="sm"
disabled={done}
onClick={() => setCount((current) => current + 1)}
>
Log next event
</Button>
<Button size="sm" variant="outline" onClick={() => setCount(2)}>
Reset
</Button>
</div>
<Timeline
aria-label="Agent run events"
items={runEvents.slice(0, count)}
presentation="flow"
reveal="stagger"
/>
</div>
);
}Examples that combine components for common tasks.
LLM story
A publication-style vertical history showing how LLMs moved from research architecture to everyday product workflows.
Status: Complete Attention changes the map
The Transformer made attention the core primitive, giving language models a cleaner way to learn context at scale.
Status: Complete Scale becomes the story
Large pretrained models showed that more data, compute, and parameters could unlock useful few-shot behavior.
Status: Complete Chat becomes the interface
Conversational assistants made LLMs feel less like research demos and more like everyday software.
Status: Current Models become teammates
LLMs now read, write, see, call tools, and coordinate multi-step work across product workflows.
Show sourceexamples/timeline/recipe-origin-story.tsx
"use client";
import { Timeline, type TimelineItemData } from "@dethink/components";
type OriginMilestone = {
year: string;
};
const originMilestones: TimelineItemData<OriginMilestone>[] = [
{
id: "transformer",
title: "Attention changes the map",
description:
"The Transformer made attention the core primitive, giving language models a cleaner way to learn context at scale.",
datetime: "2017-01-01T00:00:00Z",
dateLabel: "2017",
status: "complete",
marker: <span className="font-mono text-[10px] font-bold">T</span>,
data: { year: "2017" },
},
{
id: "scale",
title: "Scale becomes the story",
description:
"Large pretrained models showed that more data, compute, and parameters could unlock useful few-shot behavior.",
datetime: "2020-01-01T00:00:00Z",
dateLabel: "2020",
status: "complete",
marker: <span className="font-mono text-[10px] font-bold">S</span>,
data: { year: "2020" },
},
{
id: "chat",
title: "Chat becomes the interface",
description:
"Conversational assistants made LLMs feel less like research demos and more like everyday software.",
datetime: "2022-01-01T00:00:00Z",
dateLabel: "2022",
status: "complete",
marker: <span className="font-mono text-[10px] font-bold">C</span>,
data: { year: "2022" },
},
{
id: "agents",
title: "Models become teammates",
description:
"LLMs now read, write, see, call tools, and coordinate multi-step work across product workflows.",
datetime: "2026-01-01T00:00:00Z",
dateLabel: "2026",
status: "current",
marker: <span className="font-mono text-[10px] font-bold">A</span>,
data: { year: "2026" },
},
];
export function TimelineRecipeOriginStory() {
return (
<Timeline<OriginMilestone>
aria-label="Story of LLMs"
items={originMilestones}
mode="story"
/>
);
}Deployment history
Statuses carry rollout health — including a rollback marked error — and controlled selection drives a details panel showing each deployment's commit and author from its typed payload.
Status: Complete v1.4.0 → production
Date suite components released.
Status: Warning v1.4.1 → canary
Latency regression flagged on p99.
Status: Error v1.4.1 → production
Rolled back after checkout error spike.
Status: Complete v1.4.2 → production
Hotfix for date parsing in Safari.
v1.4.1 → production
Commit 38385e3 · deployed by Miguel
Show sourceexamples/timeline/recipe-deploy-history.tsx
"use client";
import { useState } from "react";
import { Timeline, type TimelineItemData } from "@dethink/components";
type DeployPayload = { sha: string; author: string };
const deploys: TimelineItemData<DeployPayload>[] = [
{
id: "d-2214",
title: "v1.4.2 → production",
description: "Hotfix for date parsing in Safari.",
datetime: "2026-07-04T08:41:00Z",
dateLabel: "Today 08:41",
status: "complete",
data: { sha: "f642257", author: "Dana" },
},
{
id: "d-2213",
title: "v1.4.1 → production",
description: "Rolled back after checkout error spike.",
datetime: "2026-07-03T16:20:00Z",
dateLabel: "Yesterday 16:20",
status: "error",
data: { sha: "38385e3", author: "Miguel" },
},
{
id: "d-2212",
title: "v1.4.1 → canary",
description: "Latency regression flagged on p99.",
datetime: "2026-07-03T14:05:00Z",
dateLabel: "Yesterday 14:05",
status: "warning",
data: { sha: "38385e3", author: "Miguel" },
},
{
id: "d-2211",
title: "v1.4.0 → production",
description: "Date suite components released.",
datetime: "2026-07-01T11:32:00Z",
dateLabel: "Jul 1 11:32",
status: "complete",
data: { sha: "17f7ab3", author: "Priya" },
},
];
/**
* An interactive deployment history: statuses carry the health of each
* rollout, and selecting an event surfaces its payload — commit and author —
* in a details panel driven by the controlled selection.
*/
export function TimelineRecipeDeployHistory() {
const [selectedId, setSelectedId] = useState<string | null>("d-2213");
const selected = deploys.find((deploy) => deploy.id === selectedId);
return (
<div className="space-y-4">
<Timeline
aria-label="Deployment history"
items={deploys}
selectedId={selectedId}
onSelectedIdChange={setSelectedId}
/>
<div
aria-live="polite"
className="border-border mx-auto max-w-md rounded-lg border px-4 py-3 text-sm"
>
{selected ? (
<>
<p className="font-medium">{selected.title}</p>
<p className="text-muted-foreground mt-0.5">
Commit <span className="font-mono">{selected.data?.sha}</span> ·
deployed by {selected.data?.author}
</p>
</>
) : (
<p className="text-muted-foreground">
Select a deployment for details.
</p>
)}
</div>
</div>
);
}Timeline is data-driven: items carry the content, and the component handles layout, scale, and interaction.
| Prop | What it does | Default |
|---|---|---|
itemsTimelineItemData[] | Event data: id, title, description, datetime/dateLabel, status, optional marker and typed payload via data. | Not set |
mode"events" | "progress" | "story" | Dated event history, undated progress sequence, or static editorial story timeline. | "events" |
status (per item)"neutral" | "complete" | "current" | "upcoming" | "warning" | "error" | Health/progress tone of each item's marker and card. | "neutral" |
orientation / layout"horizontal" | "vertical" / layout variants | Axis of the track and how item cards stack around it. | horizontal |
scale / ordertime scale / chronological order | How datetimes map to track distance and which direction time flows. | auto |
selectedId / defaultSelectedId / onSelectedIdChangestring | null / string | null / (id) => void | Controlled or uncontrolled selection; arrow keys move between items. | Not set |
presentation"canvas" | "flow" | Pannable/zoomable plane, or a static document-flow list with markers, rail, and compact cards. | "canvas" ("flow" for story) |
reveal / revealOptions"none" | "stagger" | "all" / trigger, interval, duration, initialDelay | Animated item entrance for the flow presentation — staggered or all at once, on mount, in view, or manually. | "none" |
revealCount / onItemReveal / onRevealCompletenumber / (id, index) => void / () => void | Controlled reveal progression for the manual trigger, plus per-item and completion callbacks. Appended items animate in as their own batch. | Not set |
interactiveboolean | Disables selection for purely presentational timelines. | true |
viewportTimelineViewportOptions | Zoom and pan options for long histories (defaultZoom, limits). | Not set |
renderItemTimelineItemRenderer | Custom item rendering with access to the typed payload. | built-in card |