Timeline

Timeline

An ordered list of steps connected by indicators and separator lines. Tracks an active step and lays out vertically or horizontally.

Playground

Project initialized

Bootstrapped the repository and set up CI.

Beta release

Shipped to internal testers for feedback.

Public launch

Docs published and signups open.
orientation
steps
activeStep
<Timeline defaultValue={2}>
  <TimelineItem step={1}>
    <TimelineHeader>
      <TimelineDate>Jan 2026</TimelineDate>
      <TimelineTitle>Project initialized</TimelineTitle>
    </TimelineHeader>
    <TimelineIndicator />
    <TimelineSeparator />
    <TimelineContent>Bootstrapped the repository and set up CI.</TimelineContent>
  </TimelineItem>
  <TimelineItem step={2}>
    <TimelineHeader>
      <TimelineDate>Feb 2026</TimelineDate>
      <TimelineTitle>Beta release</TimelineTitle>
    </TimelineHeader>
    <TimelineIndicator />
    <TimelineSeparator />
    <TimelineContent>Shipped to internal testers for feedback.</TimelineContent>
  </TimelineItem>
  <TimelineItem step={3}>
    <TimelineHeader>
      <TimelineDate>Mar 2026</TimelineDate>
      <TimelineTitle>Public launch</TimelineTitle>
    </TimelineHeader>
    <TimelineIndicator />
    <TimelineSeparator />
    <TimelineContent>Docs published and signups open.</TimelineContent>
  </TimelineItem>
</Timeline>

Preview

The default orientation stacks items vertically. Each TimelineItem takes a step number and composes a TimelineHeader (with TimelineDate and TimelineTitle), the dot TimelineIndicator, the connecting TimelineSeparator, and TimelineContent.

Project initialized

Bootstrapped the repository and set up CI.

Beta release

Shipped to internal testers for feedback.

Public launch

Docs published and signups open.
<Timeline defaultValue={2}>
  <TimelineItem step={1}>
    <TimelineHeader>
      <TimelineDate>Jan 2026</TimelineDate>
      <TimelineTitle>Project initialized</TimelineTitle>
    </TimelineHeader>
    <TimelineIndicator />
    <TimelineSeparator />
    <TimelineContent>Bootstrapped the repository and set up CI.</TimelineContent>
  </TimelineItem>
  <TimelineItem step={2}>
    <TimelineHeader>
      <TimelineDate>Feb 2026</TimelineDate>
      <TimelineTitle>Beta release</TimelineTitle>
    </TimelineHeader>
    <TimelineIndicator />
    <TimelineSeparator />
    <TimelineContent>Shipped to internal testers for feedback.</TimelineContent>
  </TimelineItem>
  <TimelineItem step={3}>
    <TimelineHeader>
      <TimelineDate>Mar 2026</TimelineDate>
      <TimelineTitle>Public launch</TimelineTitle>
    </TimelineHeader>
    <TimelineIndicator />
    <TimelineSeparator />
    <TimelineContent>Docs published and signups open.</TimelineContent>
  </TimelineItem>
</Timeline>

Usage

import {
  Timeline,
  TimelineContent,
  TimelineDate,
  TimelineHeader,
  TimelineIndicator,
  TimelineItem,
  TimelineSeparator,
  TimelineTitle,
} from "@/components/reui/timeline"
<Timeline defaultValue={1}>
  <TimelineItem step={1}>
    <TimelineHeader>
      <TimelineDate>Today</TimelineDate>
      <TimelineTitle>Order placed</TimelineTitle>
    </TimelineHeader>
    <TimelineIndicator />
    <TimelineSeparator />
    <TimelineContent>Your order is being prepared.</TimelineContent>
  </TimelineItem>
</Timeline>

Horizontal

orientation="horizontal" lays the steps out in a row – indicators and separators move above the content, and each item stretches with flex-1.

Project initialized

Bootstrapped the repository and set up CI.

Beta release

Shipped to internal testers for feedback.

Public launch

Docs published and signups open.
<Timeline orientation="horizontal" defaultValue={2}>
  <TimelineItem step={1}>
    <TimelineHeader>
      <TimelineDate>Jan 2026</TimelineDate>
      <TimelineTitle>Project initialized</TimelineTitle>
    </TimelineHeader>
    <TimelineIndicator />
    <TimelineSeparator />
    <TimelineContent>Bootstrapped the repository and set up CI.</TimelineContent>
  </TimelineItem>
  {/* ...more items */}
</Timeline>

Controlled

Pass value and onValueChange to drive the active step from your own state – useful for steppers and wizards.

Project initialized

Bootstrapped the repository and set up CI.

Beta release

Shipped to internal testers for feedback.

Public launch

Docs published and signups open.
Step 1 of 3
const [active, setActive] = React.useState(1)

<Timeline value={active} onValueChange={setActive}>
  {steps.map((s) => (
    <TimelineItem key={s.step} step={s.step}>
      <TimelineHeader>
        <TimelineDate>{s.date}</TimelineDate>
        <TimelineTitle>{s.title}</TimelineTitle>
      </TimelineHeader>
      <TimelineIndicator />
      <TimelineSeparator />
      <TimelineContent>{s.body}</TimelineContent>
    </TimelineItem>
  ))}
</Timeline>

<Button onClick={() => setActive((v) => v + 1)}>Next</Button>

Custom indicators

TimelineIndicator accepts children, a className, and a render prop – swap the plain dot for icons, avatars or status colors, and style the completed state through the group-data-completed/timeline-item variant.

Branch created

Step 1 of the release pipeline.

Component scaffolded

Step 2 of the release pipeline.

Shipped

Step 3 of the release pipeline.
<TimelineIndicator className="flex items-center justify-center border-0 bg-primary/10 group-data-completed/timeline-item:bg-primary group-data-completed/timeline-item:text-primary-foreground">
  <CheckIcon className="size-2.5" />
</TimelineIndicator>

// or render any element in place of the dot
<TimelineIndicator
  className="size-7 rounded-full border-none"
  render={<Avatar className="size-7">...</Avatar>}
/>

API reference

Timeline is a compound component. The root holds the active step in context (uncontrolled via defaultValue, controlled via value) and each TimelineItem compares its step against it to derive the completed state. All parts render plain elements and accept className plus standard props.

Timeline

PropTypeDefaultDescription
defaultValuenumber1Initial active step for uncontrolled usage. Items whose step is at or before it are marked completed.
valuenumber–Controlled active step. When set, internal state is bypassed.
onValueChange(value: number) => void–Called when the active step changes.
orientation"vertical" | "horizontal""vertical"Layout axis – reflected on the root as data-orientation, which every part reads for its positioning.

TimelineItem

PropTypeDefaultDescription
stepnumber–This item's position in the sequence. When step <= the active step, the item gets data-completed, which fills its indicator border and the previous separator.
ComponentDescription
TimelineHeaderWrapper for the date and title above the content (data-slot="timeline-header").
TimelineDateSmall muted timestamp rendered as a time element. Supports a render prop to swap the tag.
TimelineTitleStep heading rendered as an h3 (data-slot="timeline-title").
TimelineIndicatorThe circular marker (aria-hidden). Border fills with the primary color when the item is completed. Supports children and a render prop for icons or avatars.
TimelineSeparatorConnecting line between indicators (data-slot="timeline-separator", aria-hidden). Hidden on the last item; turns solid primary when the following item is completed.
TimelineContentBody copy for the step (data-slot="timeline-content").

Styling hooks

The root exposes data-slot="timeline" and data-orientation; items expose data-slot="timeline-item" and, when at or before the active step, data-completed. Parts position themselves with group variants (group/timeline, group/timeline-item), so you can re-position an individual indicator or separator per item by overriding the same group-data-[orientation=...] utilities – the showcase uses this to build avatar feeds and activity logs. The indicator and separator are aria-hidden, keeping the accessible output to the dates, titles and content.

Search documentation

Search the component docs