Timeline
A composable, read-only chronology for activity feeds, audit trails, incident logs, and centered milestone roadmaps.
Import
import { Timeline } from '@darkcode-ui/react';Usage
Timeline is for read-only chronology: activity feeds, audit trails, incident history, release logs, and milestone roadmaps. Use Stepper when the user is moving through a known sequence where current, complete, and upcoming steps are the primary meaning.
import {Timeline} from "@darkcode-ui/react";
type Status = "default" | "current" | "success" | "warning" | "danger" | "muted";
const events: {title: string; time: string; description: string; status: Status}[] = [Anatomy
Import the Timeline component and access all parts using dot notation.
import { Timeline } from '@darkcode-ui/react';
export default () => (
<Timeline>
<Timeline.Item>
<Timeline.Rail>
<Timeline.Marker />
<Timeline.Connector />
</Timeline.Rail>
<Timeline.Content>
<h3>Event title</h3>
<time dateTime="2026-05-22">May 22, 2026</time>
<p>Event details</p>
</Timeline.Content>
</Timeline.Item>
</Timeline>
);Timeline intentionally owns only the chronology layout. It renders an ol with li items, keeps
connectors decorative, hides empty markers from assistive technology, and marks status="current"
items with aria-current="true". Use semantic HTML and other DarkCode UI components such as
Card, Chip, and
Avatar inside Timeline.Content for the event content itself.
The Timeline.Rail, Timeline.Marker, and Timeline.Connector parts are optional — when omitted,
each renders a sensible default. The example below is equivalent to the verbose anatomy above:
<Timeline>
<Timeline.Item status="success">
<Timeline.Content>Event title</Timeline.Content>
</Timeline.Item>
</Timeline>Content Subparts
Instead of hand-rolling markup, compose the optional Timeline.Header, Timeline.Title,
Timeline.Time, and Timeline.Description parts inside Timeline.Content. Timeline.Time renders a
semantic <time> element and Timeline.Title renders an <h3>.
import {Timeline} from "@darkcode-ui/react";
type Status = "default" | "current" | "success" | "muted";
const events: {title: string; time: string; description: string; status: Status}[] = [Centered Milestones
Set axis="center" to place the rail in the middle, and placement="alternate" to flip content
from side to side by item index — ideal for roadmaps and milestone timelines.
import {Timeline} from "@darkcode-ui/react";
import {Icon} from "@iconify/react";
type Status = "default" | "current" | "success";
Studio Review
Compose avatars as markers and chips inside Timeline.Content to build rich review feeds.
import {Avatar, Chip, Timeline} from "@darkcode-ui/react";
type Status = "default" | "current" | "success" | "warning";
type ChipColor = "accent" | "success" | "warning" | "default";
Expandable
Reveal extra detail on demand. Timeline.Collapsible wraps the content in a React Aria Disclosure;
Timeline.Trigger toggles it, Timeline.Indicator is a chevron that rotates when expanded, and
Timeline.Details is the animated panel. Pass defaultExpanded (or controlled isExpanded /
onExpandedChange) to Timeline.Collapsible.
import {Timeline} from "@darkcode-ui/react";
type Status = "default" | "current" | "success" | "warning";
const events: {Interactive
Make an event navigable or clickable with Timeline.Action, which renders a React Aria Button (or
a Link when href is set) as a full-width surface with hover, press, and keyboard-focus states.
import {Timeline} from "@darkcode-ui/react";
import {Icon} from "@iconify/react";
type Status = "default" | "current" | "success" | "warning";
Compact Log
Use density="compact" with size="sm" and align="center" for terse, log-style chronologies.
import {Timeline} from "@darkcode-ui/react";
type Status = "default" | "current" | "success" | "warning" | "danger" | "muted";
const log: {time: string; message: string; status: Status}[] = [Incident Response
Status tones (success, warning, danger, current) color both the marker and the connector
leading away from it, making severity easy to scan.
import {Chip, Timeline} from "@darkcode-ui/react";
import {Icon} from "@iconify/react";
type Status = "default" | "current" | "success" | "warning" | "danger";
type ChipColor = "success" | "warning" | "danger" | "accent";Grouped Sections
Cluster events under sticky date or category headings with Timeline.Section and
Timeline.SectionHeading. Each section renders its own ordered sub-list, and item indices stay
continuous across groups (so useTimelineItem().index keeps counting). The heading pins to the top
while its group scrolls.
import {Timeline} from "@darkcode-ui/react";
type Status = "default" | "current" | "success" | "warning" | "muted";
const groups: {Version History
import {Avatar, Chip, Timeline} from "@darkcode-ui/react";
type Status = "default" | "current" | "muted";
const revisions: {Scroll Reveal
Set reveal on the root to animate items in as they scroll into view (backed by an
IntersectionObserver). The animation is automatically disabled when the user prefers reduced
motion. Override per item with the reveal prop on Timeline.Item.
import {Timeline} from "@darkcode-ui/react";
type Status = "default" | "current" | "success" | "warning" | "muted";
const events: {title: string; time: string; description: string; status: Status}[] = [Horizontal
Set orientation="horizontal" to lay the rail along the x-axis with content below each marker —
useful for compact step or progress-style chronologies. The list scrolls horizontally when it
overflows.
import {Timeline} from "@darkcode-ui/react";
import {Icon} from "@iconify/react";
type Status = "default" | "current" | "success";
Repository Activity
import {Chip, Timeline} from "@darkcode-ui/react";
import {Icon} from "@iconify/react";
type Status = "default" | "current" | "success" | "muted";
type ChipColor = "success" | "accent" | "warning" | "default";Loading & Load More
Render Timeline.Skeleton placeholders while data loads, and Timeline.LoadMore to paginate. Pass
onLoadMore plus isLoading; add auto to trigger loading automatically when the row scrolls into
view (infinite scroll).
"use client";
import {Timeline} from "@darkcode-ui/react";
import {useState} from "react";
Virtualized
For very long, data-driven feeds, pass virtualized with an items array, a renderItem
function, an estimateRowHeight, and a maxHeight. Only the visible rows (plus overscan) are
rendered inside a scroll container, preserving scroll height with spacer rows. Virtualized mode is
best for roughly uniform row heights and is not combined with sections or expandable items.
"use client";
import {Timeline} from "@darkcode-ui/react";
type Status = "default" | "current" | "success" | "warning" | "muted";Split Content
In a centered timeline, render two Timeline.Content parts with explicit side props to place
metadata (such as a timestamp) opposite the main content.
import {Timeline} from "@darkcode-ui/react";
type Status = "default" | "current" | "success" | "muted";
const schedule: {time: string; date: string; title: string; description: string; status: Status}[] =Styling
Passing Tailwind CSS classes
import { Timeline } from "@darkcode-ui/react";
function ReleaseLog() {
return (
<Timeline className="w-full max-w-md">
<Timeline.Item status="success">
<Timeline.Content className="gap-0.5">
<h3 className="text-sm font-semibold text-foreground">v2.4.0 released</h3>
<p className="text-sm text-muted">Centered axis and split content shipped.</p>
</Timeline.Content>
</Timeline.Item>
</Timeline>
);
}Customizing the component classes
To customize the Timeline component classes, you can use the @layer components directive.
Learn more.
@layer components {
.timeline {
--timeline-row-gap: 2rem;
}
.timeline__marker--current {
@apply bg-accent;
}
}DarkCode UI follows the BEM methodology to ensure component variants and states are reusable and easy to customize.
CSS Classes
The Timeline component uses these CSS classes (View source styles):
Base, Axis & Size Classes
.timeline- Base ordered-list layout (two-column rail + content).timeline--axis-center- Centers the rail and enables three-column content placement.timeline--sm- Small markers and tighter rhythm.timeline--md- Medium size (default).timeline--lg- Large markers and looser rhythm.timeline--compact- Reduced vertical rhythm between events
Element Classes
.timeline__item- A single event row.timeline__rail- Column holding the marker and connector.timeline__marker- The event marker dot or icon container.timeline__connector- The decorative line between markers.timeline__content- The event content area
Status Modifiers
.timeline__marker--current/--success/--warning/--danger/--muted- Marker tones.timeline__item--current/--success/--warning/--danger- Tints the trailing connector
Side Modifiers (centered axis)
.timeline__content--start/.timeline__item--start- Content occupies the start side.timeline__content--end/.timeline__item--end- Content occupies the end side.timeline__content--align-center/.timeline__item--align-center- Vertically centers content
API Reference
Timeline
The root component. Renders an ordered list and provides axis, placement, size, density, and item alignment context.
| Prop | Type | Default | Description |
|---|---|---|---|
axis | 'start' | 'center' | 'start' | Position of the timeline rail |
placement | 'start' | 'end' | 'alternate' | 'end' | Default side for item content; alternate alternates by item index |
size | 'sm' | 'md' | 'lg' | 'md' | Marker and text size |
density | 'compact' | 'comfortable' | 'comfortable' | Vertical rhythm between events |
orientation | 'vertical' | 'horizontal' | 'vertical' | Layout direction of the timeline |
itemAlign | 'start' | 'center' | 'start' | Default vertical alignment for item content |
reveal | boolean | false | Animate items in as they scroll into view (respects reduced motion) |
virtualized | boolean | false | Window long feeds (requires items + renderItem) |
items | readonly T[] | - | Data rows for virtualized mode |
renderItem | (item: T, index: number) => ReactNode | - | Renders each virtualized row |
estimateRowHeight | number | 64 | Estimated row height (px) for virtualization |
maxHeight | number | string | 400 | Scroll-container height for virtualized mode |
overscan | number | 5 | Extra rows rendered above/below the viewport |
children | ReactNode | - | Timeline items |
Also supports all native ol HTML attributes.
Timeline.Item
A single event in the timeline.
| Prop | Type | Default | Description |
|---|---|---|---|
status | 'default' | 'current' | 'success' | 'warning' | 'danger' | 'muted' | 'default' | Marker tone |
align | 'start' | 'center' | inherited | Vertical alignment for item content |
side | 'start' | 'end' | inherited | Content side for centered timelines |
reveal | boolean | inherited | Animate this item in on scroll |
children | ReactNode | - | Item parts |
Also supports all native li HTML attributes. Sets aria-current="true" when status="current".
Timeline.Rail
Rail wrapper for the marker and connector. If omitted, Timeline.Item renders a default rail.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | Marker and connector content |
Also supports all native span HTML attributes.
Timeline.Marker
The event marker. If omitted, Timeline.Rail renders a default marker. Empty markers are decorative
and hidden from assistive technology.
| Prop | Type | Default | Description |
|---|---|---|---|
status | 'default' | 'current' | 'success' | 'warning' | 'danger' | 'muted' | item status | Marker tone override |
children | ReactNode | - | Custom marker content |
Also supports all native span HTML attributes.
Timeline.Connector
Connector line after the current item. It is hidden automatically for the last item.
| Prop | Type | Default | Description |
|---|---|---|---|
force | boolean | false | Force rendering even on the last item |
children | ReactNode | - | Custom connector content |
Also supports all native span HTML attributes.
Timeline.Content
Main event content. In centered timelines, side controls which side of the axis it occupies.
| Prop | Type | Default | Description |
|---|---|---|---|
side | 'start' | 'end' | item side | Content side |
children | ReactNode | - | Content parts |
Also supports all native div HTML attributes.
Timeline.Header
Groups a title and timestamp on one row. Renders a div.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | Header content (typically Title + Time) |
Also supports all native div HTML attributes.
Timeline.Title
The event title. Renders an h3.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | Title text |
Also supports all native h3 HTML attributes.
Timeline.Time
A timestamp rendered as a semantic time element.
| Prop | Type | Default | Description |
|---|---|---|---|
dateTime | string | - | Machine-readable timestamp |
children | ReactNode | - | Human-readable time |
Also supports all native time HTML attributes.
Timeline.Description
Secondary descriptive text. Renders a p.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | Description text |
Also supports all native p HTML attributes.
Timeline.Collapsible
Wraps expandable content in a React Aria Disclosure. Place inside Timeline.Content.
| Prop | Type | Default | Description |
|---|---|---|---|
isExpanded | boolean | - | Controlled expanded state |
defaultExpanded | boolean | false | Uncontrolled initial expanded state |
onExpandedChange | (isExpanded: boolean) => void | - | Called when expansion changes |
isDisabled | boolean | false | Disables the disclosure |
children | ReactNode | - | Trigger + Details |
Timeline.Trigger
The button that toggles the collapsible. Renders a React Aria Button.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | Trigger content (title, time, indicator) |
Also supports all React Aria Button props.
Timeline.Indicator
A chevron icon that rotates when the collapsible is expanded. Pass a custom element as children to
replace the default chevron.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactElement | chevron | Custom indicator element |
Timeline.Details
The animated collapsible panel. Renders a React Aria DisclosurePanel.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | Detail content |
Timeline.Action
An interactive item surface. Renders a React Aria Button, or a Link when href is set.
| Prop | Type | Default | Description |
|---|---|---|---|
href | string | - | Renders a navigable link instead of a button |
onPress | (e: PressEvent) => void | - | Press handler (button mode) |
isDisabled | boolean | false | Disables the action |
children | ReactNode | - | Surface content |
Also supports the underlying React Aria Button / Link props.
Timeline.Section
Groups items under a heading with its own continuous rail. Renders an li containing a nested ol.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | A Timeline.SectionHeading plus Timeline.Items |
Also supports all native li HTML attributes.
Timeline.SectionHeading
A sticky group label (e.g. a date). Renders a div.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | Heading content |
Also supports all native div HTML attributes.
Timeline.Skeleton
Renders placeholder rows that mirror the item layout while content loads.
| Prop | Type | Default | Description |
|---|---|---|---|
count | number | 3 | Number of placeholder rows |
animationType | 'none' | 'pulse' | 'shimmer' | 'shimmer' | Skeleton animation |
Timeline.LoadMore
A trailing row that loads the next page, via a button or automatically on scroll.
| Prop | Type | Default | Description |
|---|---|---|---|
onLoadMore | () => void | - | Called to load the next page |
isLoading | boolean | false | Shows a spinner instead of the button |
auto | boolean | false | Trigger onLoadMore when scrolled into view |
children | ReactNode | "Load more" | Button label |
useTimelineItem
Hook to access per-item context from descendants of Timeline.Item.
| Property | Type | Description |
|---|---|---|
align | 'start' | 'center' | Resolved item content alignment |
index | number | Zero-based item index |
isLast | boolean | Whether this is the final timeline item |
side | 'start' | 'end' | Resolved item side |
status | 'default' | 'current' | 'success' | 'warning' | 'danger' | 'muted' | Item marker status |