27.7k

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.

PropTypeDefaultDescription
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
revealbooleanfalseAnimate items in as they scroll into view (respects reduced motion)
virtualizedbooleanfalseWindow long feeds (requires items + renderItem)
itemsreadonly T[]-Data rows for virtualized mode
renderItem(item: T, index: number) => ReactNode-Renders each virtualized row
estimateRowHeightnumber64Estimated row height (px) for virtualization
maxHeightnumber | string400Scroll-container height for virtualized mode
overscannumber5Extra rows rendered above/below the viewport
childrenReactNode-Timeline items

Also supports all native ol HTML attributes.

Timeline.Item

A single event in the timeline.

PropTypeDefaultDescription
status'default' | 'current' | 'success' | 'warning' | 'danger' | 'muted''default'Marker tone
align'start' | 'center'inheritedVertical alignment for item content
side'start' | 'end'inheritedContent side for centered timelines
revealbooleaninheritedAnimate this item in on scroll
childrenReactNode-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.

PropTypeDefaultDescription
childrenReactNode-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.

PropTypeDefaultDescription
status'default' | 'current' | 'success' | 'warning' | 'danger' | 'muted'item statusMarker tone override
childrenReactNode-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.

PropTypeDefaultDescription
forcebooleanfalseForce rendering even on the last item
childrenReactNode-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.

PropTypeDefaultDescription
side'start' | 'end'item sideContent side
childrenReactNode-Content parts

Also supports all native div HTML attributes.

Timeline.Header

Groups a title and timestamp on one row. Renders a div.

PropTypeDefaultDescription
childrenReactNode-Header content (typically Title + Time)

Also supports all native div HTML attributes.

Timeline.Title

The event title. Renders an h3.

PropTypeDefaultDescription
childrenReactNode-Title text

Also supports all native h3 HTML attributes.

Timeline.Time

A timestamp rendered as a semantic time element.

PropTypeDefaultDescription
dateTimestring-Machine-readable timestamp
childrenReactNode-Human-readable time

Also supports all native time HTML attributes.

Timeline.Description

Secondary descriptive text. Renders a p.

PropTypeDefaultDescription
childrenReactNode-Description text

Also supports all native p HTML attributes.

Timeline.Collapsible

Wraps expandable content in a React Aria Disclosure. Place inside Timeline.Content.

PropTypeDefaultDescription
isExpandedboolean-Controlled expanded state
defaultExpandedbooleanfalseUncontrolled initial expanded state
onExpandedChange(isExpanded: boolean) => void-Called when expansion changes
isDisabledbooleanfalseDisables the disclosure
childrenReactNode-Trigger + Details

Timeline.Trigger

The button that toggles the collapsible. Renders a React Aria Button.

PropTypeDefaultDescription
childrenReactNode-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.

PropTypeDefaultDescription
childrenReactElementchevronCustom indicator element

Timeline.Details

The animated collapsible panel. Renders a React Aria DisclosurePanel.

PropTypeDefaultDescription
childrenReactNode-Detail content

Timeline.Action

An interactive item surface. Renders a React Aria Button, or a Link when href is set.

PropTypeDefaultDescription
hrefstring-Renders a navigable link instead of a button
onPress(e: PressEvent) => void-Press handler (button mode)
isDisabledbooleanfalseDisables the action
childrenReactNode-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.

PropTypeDefaultDescription
childrenReactNode-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.

PropTypeDefaultDescription
childrenReactNode-Heading content

Also supports all native div HTML attributes.

Timeline.Skeleton

Renders placeholder rows that mirror the item layout while content loads.

PropTypeDefaultDescription
countnumber3Number 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.

PropTypeDefaultDescription
onLoadMore() => void-Called to load the next page
isLoadingbooleanfalseShows a spinner instead of the button
autobooleanfalseTrigger onLoadMore when scrolled into view
childrenReactNode"Load more"Button label

useTimelineItem

Hook to access per-item context from descendants of Timeline.Item.

PropertyTypeDescription
align'start' | 'center'Resolved item content alignment
indexnumberZero-based item index
isLastbooleanWhether this is the final timeline item
side'start' | 'end'Resolved item side
status'default' | 'current' | 'success' | 'warning' | 'danger' | 'muted'Item marker status

On this page