Timeline
Follow what happened, newest first, grouped by day.
pnpm dlx shadcn@latest add @uiarc/timelineLive · keyboard ready
Checkout redesign
Project activity
Today, 4 updates
Friday, September 18, 3 updates
Thursday, September 17, 2 updates
- Project history, audit logs, and deploy streams where recency matters.
- Live feeds where new updates slide in at the top.
- Rows that expand in place to show logs or detail.
- Use sortable-data-table when people sort or compare.
- Use stepper for progress through fixed steps.
Installation
Add Timeline with the shadcn CLI, or copy the source by hand.
pnpm dlx shadcn@latest add @uiarc/timelineAdds the component and its local dependencies, and installs motion, lucide-react. First time? Add the @uiarc registry to components.json, or use the full URL:
example.tsx
import { Timeline } from "@/registry/components/timeline/timeline"; const events = [ { id: "e1", at: "2026-09-22T09:12:00Z", actor: "Maya", title: "merged Checkout redesign into main", meta: "PR #482" }, { id: "e2", at: "2026-09-22T08:40:00Z", title: "Deploy failed", tone: "danger" as const, detail: <pre>Build step exited 1</pre> },]; export function Activity({ now }: { now: number }) { return <Timeline events={events} now={now} label="Project activity" maxHeight={420} />;}Timeline
A vertical activity feed grouped by day with pinned day labels and rows that expand in place.
PropTypeDefaultDescription
eventsRequired{ id: string; at: string | number; actor?: string; title: string; meta?: string; detail?: ReactNode; avatar?: string; icon?: ReactNode; tone?: "neutral" | "success" | "danger" }[]–Updates in any order; newest shows first. Rows with detail are expandable.nowRequirednumber–Reference time in epoch ms for relative labels and day groups. Pass a ticking clock to keep labels fresh.labelRequiredstring–Accessible name for the feed.timeZonestring"UTC"Time zone for day groups and clock times.localestring"en-US"Formatting locale.maxHeightnumber | string–Height of the scrolling area. Without it the feed grows with the page.scrollToNewbooleantrueScrolls back to the top when a new update arrives.defaultExpandedstring[][]Event ids expanded on mount.headingLevel2 | 3 | 4 | 5 | 63Heading level for day labels.classNamestring–Class for the root.- ArrowDownorArrowUp
- Moves between expandable rows.
- HomeorEnd
- Jumps to the first or last expandable row.
- EnterorSpace
- Expands or collapses the focused row.
- The feed is a labelled role="region"; day labels are headings at headingLevel with a hidden update count.
- Expandable rows are buttons with aria-expanded and aria-controls; rows without detail are not interactive.
- Times use a time element with the full date in hidden text, and new updates are announced in a status region.
- Say the outcome in the title, since tone is color only.
- The connecting line draws as rows come into view and markers pop in.
- New updates slide in at the top while the rest glide down; details expand on a spring.
- Reduced motion replaces travel with short fades and instant height changes.
- Day labels stay pinned while updates scroll under them, inside maxHeight or the page.
- Below 420px row padding tightens so text keeps its width.
- Events are not virtualized; set maxHeight for long feeds and trim old events.
- Pass a now that ticks about once a minute rather than every second, since it re-renders every row.
Notes for AI
Give your coding assistant the Markdown reference instead of screenshots.
- Use for project history, audit logs, and deploy streams where order and recency matter. Use sortable-data-table when people sort or compare.
- Pass a ticking now (for example updated every minute) so relative times stay current, and a fixed timeZone to avoid hydration mismatches.
The full library index for assistants is at /llms.txt.