Skip to content

ComponentsDisplay

Timeline

A vertical list of events, such as an activity feed, an order's shipping history or a ticket's audit trail. Each item has a dot, icon or avatar, a title, a time and optional content, joined by connector lines. Comes in default and compact densities, with tone-colored markers and an option to hide the connector.

Source
  1. Maya Chen opened #482
    Add retry with backoff to the webhook dispatcher.
  2. Jonas Weber left a review
    Looks good. Can we cap the delay at 30 seconds?
  3. Maya Chen merged into main

Installation

pnpm dlx shadcn@latest add @desyne/timeline

The CLI installs dependencies and any other components this one uses.

Usage

tsx
import {
  Timeline,
  TimelineContent,
  TimelineDescription,
  TimelineHeader,
  TimelineIndicator,
  TimelineItem,
  TimelineTime,
  TimelineTitle,
} from "@/components/ui/timeline";
tsx
<Timeline aria-label="Shipment history">
  <TimelineItem>
    <TimelineIndicator color="success" />
    <TimelineContent>
      <TimelineHeader>
        <TimelineTitle>Order delivered</TimelineTitle>
        <TimelineTime dateTime="2026-10-04T14:41">Today, 2:41 PM</TimelineTime>
      </TimelineHeader>
      <TimelineDescription>Left at the front door</TimelineDescription>
    </TimelineContent>
  </TimelineItem>
</Timeline>

The timeline is static markup with no "use client", so it renders in server components.

When to use

  • Timeline: things that already happened, in order, where when they happened matters (activity, history, audit logs, tracking).
  • Stepper: steps the user still has to complete.
  • Item: a list of entities, not events.
  • Table: large logs that users filter, sort or export.

Anatomy

tsx
<Timeline>                     {/* <ol>, variant, connector */}
  <TimelineItem>               {/* <li> */}
    <TimelineIndicator />      {/* dot, icon tile or media + connector */}
    <TimelineContent>          {/* fills the rest of the row */}
      <TimelineHeader>         {/* title and time on one row */}
        <TimelineTitle />
        <TimelineTime />       {/* <time> */}
      </TimelineHeader>
      <TimelineDescription />  {/* body text or any content */}
    </TimelineContent>
  </TimelineItem>
</Timeline>
PartRendersNotes
Timeline<ol>Sets --timeline-indicator (marker size) and --timeline-gap (space between items) for the chosen variant.
TimelineItem<li>A row: marker column plus content.
TimelineIndicator<div aria-hidden>With no children, a dot. With children, a 28px round icon tile (variant="icon") or a circle that an image or avatar fills (variant="media"). Draws the connector down to the next item.
TimelineContent<div>Aligns its first line with the marker and adds the gap below each item.
TimelineHeader<div>Flex row that wraps. The time is pushed to the end.
TimelineTitle<div>Foreground text. <strong> inside is medium weight, for names.
TimelineTime<time>Muted, tabular. Pass dateTime with an ISO value.
TimelineDescription<div>Muted body text. Can hold badges, quotes or cards.

Examples

Dots

Leave TimelineIndicator empty for a dot. Without color it's a neutral ring; with color it's filled with a soft halo, useful for the latest or most important event.

  1. Order delivered
    Left at the front door · Signed by R. Patel
  2. Out for delivery
    Van 14 · Brooklyn depot
  3. Arrived at local depot
    Brooklyn, NY
  4. Shipped
    Northfold warehouse, Newark, NJ

Compact

variant="compact" shrinks markers to 20px and tightens spacing for dense activity feeds in sidebars and popovers.

  1. Ana changed status to In review
  2. Ana attached spec-v3.pdf
  3. Leo assigned the issue to Ana
  4. Leo added the label Billing
  5. Sam created the issue

Rich content

Content can be anything: a quoted reply, a badge, an attachment. Use variant="media" to fill the marker with an Avatar or image.

  1. Priya Raman replied
    I've refunded the duplicate charge. It should show on your statement within 5 business days.
  2. Refund issued
    $129.00to Visa ending 4242
  3. Daniel Kim opened the ticket
    "I was charged twice for my October subscription."

Without connector

connector={false} hides the lines (spacing stays the same), for feeds where items aren't a single continuous sequence.

  1. Payment received
    $480.00 for the Team plan, invoice INV-2041.
  2. 3 seats added
    Prorated charge of $36.00 on the next invoice.
  3. Card expiring soon
    Visa ending 4242 expires at the end of October.

Accessibility

  • The timeline is an <ol>, so screen readers announce the number of events. Add an aria-label when the context doesn't already make clear what the list is.
  • Markers are aria-hidden. If an icon or color carries meaning (e.g. failed vs. succeeded), say so in the title or description too.
  • TimelineTime renders a <time> element; pass a machine-readable dateTime alongside friendly text like "2h ago".
  • TimelineTitle is a <div>. If items are sections with their own headings, put a heading element inside it.

Styling

Data attributes

AttributeOnValues
data-slot="timeline"TimelineAlways
data-variantTimelinedefault · compact
data-connectorTimelinetrue · false
data-slot="timeline-item"TimelineItemAlways
data-slot="timeline-indicator"Marker columnAlways
data-slot="timeline-dot"DotNo children
data-slot="timeline-connector"LineAlways (hidden on the last item)
data-slot="timeline-content" / -header / -title / -time / -descriptionPartsAlways

CSS variables

VariableDefaultCompactUsed for
--timeline-indicator--spacing(7) (28px)--spacing(5) (20px)Marker size and column width
--timeline-gap--spacing(6)--spacing(3.5)Space under each item

Override them on Timeline, e.g. className="[--timeline-gap:--spacing(10)]".

API Reference

Timeline

Prop

Type

Also accepts every prop of <ol>.

TimelineIndicator

Prop

Type

Also accepts every prop of <div>.

TimelineTime

Accepts every prop of <time>, including dateTime.

TimelineItem / TimelineContent / TimelineHeader / TimelineTitle / TimelineDescription

No extra props. TimelineItem accepts every prop of <li>; the others accept every prop of <div>.

  • Stepper: steps still to come.
  • Avatar: people in activity feeds.
  • Item: lists of entities.