Add this component

npx zentauri-ui add timeline

Accessibility notes

Keyboard accessible by default with semantic markup, visible focus treatment, and tokenized states. Add descriptive labels for icon-only or decorative usage.

Dependency notes

Static imports do not pull framer-motion. Use the animated entry only when you want motion and have framer-motion installed.

Data display

Timelines for activity and history

Timelines render ordered events down a connected vertical track. Each TimelineItem carries an indicator plus a content slot for a title and supporting description, while the connector line is drawn automatically between items.

  1. Order placed

    We received your order.

  2. Processing

    Your items are being prepared.

  3. Shipped

    The package is on the way to you.

  4. Delivered

    Handed off at the front door.

Activity feed

  1. Pushed 3 commits

    main · 2 minutes ago

  2. Opened pull request

    Add timeline component · 1 hour ago

  3. Closed issue #128

    Yesterday

  1. Kickoff

    Project scope agreed with stakeholders.

  2. Design review

    Final mocks signed off.

  3. Launch

    Shipped to production.

Timeline variants playground

Pick an appearance, size, and animation transition to preview the timeline live. Toggle Show output / Show code and the snippet updates to match the selected variant.


  1. Order placed

    We received your order.

  2. Processing

    Your items are being prepared.

  3. Shipped

    The package is on the way to you.

  4. Delivered

    Handed off at the front door.

All appearances

Every shipped appearance token at a glance. Click any swatch to load it into the playground above.

Timeline API

Generated from the package prop types and variant definitions.

Timeline

TimelineProps

Variants

PropTypeDefault
sizeControls indicator size, content spacing, and text scale.
lgmdsm
md

Behavior

PropTypeDefault
appearanceDefault indicator appearance applied to every item (overridable per indicator).TimelineAppearance | undefinednone

Content

PropTypeDefault
childrenReactNodenone
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLOListElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone

TimelineContent

TimelineContentProps

Content

PropTypeDefault
childrenReactNodenone
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLDivElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone

TimelineDescription

TimelineDescriptionProps

Inherited HTML props
PropTypeDefault
childrenReactNodenone
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLParagraphElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone

TimelineIndicator

TimelineIndicatorProps

Variants

PropTypeDefault
appearanceOverride the appearance inherited from the Timeline root.
aquabluecrimsoncyandefaultelectricemeraldforestgradient-bluegradient-greengradient-indigogradient-orange+30
default

Content

PropTypeDefault
childrenReactNodenone
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLDivElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone

TimelineItem

TimelineItemProps

Content

PropTypeDefault
childrenReactNodenone
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLLIElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone

TimelineTitle

TimelineTitleProps

Inherited HTML props
PropTypeDefault
childrenReactNodenone
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLDivElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone

TimelineAnimated

TimelineAnimatedProps

animated

Behavior

PropTypeDefault
appearanceDefault indicator appearance applied to every item (overridable per indicator).TimelineAppearance | undefinednone
sizeControls indicator size, content spacing, and text scale.TimelineSize | undefinednone

Content

PropTypeDefault
childrenReactNodenone
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLOListElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone

TimelineItemAnimated

TimelineItemAnimatedProps

animated

Behavior

PropTypeDefault
staggerPer-item entrance delay multiplier in seconds (index × stagger).number | undefinednone
transitionVariantEntrance easing/duration preset. `none` renders without motion.TimelineTransition | undefinednone

Content

PropTypeDefault
childrenReactNodenone
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLLIElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone
CSS variable overrides

Timeline CSS variables

Override these timeline variables on :root, a theme selector, or a component wrapper.

285 variables

Pattern: --zui-<component>-<slot?>-<variant?>-<property>-<state?>-dark?

:root {
  --zui-timeline-indicator-default-border: oklch(55.1% 0.027 264.364 / 0.6);
  --zui-timeline-indicator-default-bg: oklch(55.1% 0.027 264.364 / 0.2);
  --zui-timeline-indicator-default-fg: oklch(21% 0.034 264.665);
  --zui-timeline-indicator-default-ring: oklch(70.7% 0.022 261.325 / 0.3);
  --zui-timeline-indicator-sky-border: oklch(68.5% 0.169 237.323 / 0.6);
  --zui-timeline-indicator-sky-bg: oklch(68.5% 0.169 237.323 / 0.2);
  --zui-timeline-indicator-sky-fg: oklch(39.1% 0.09 240.876);
  --zui-timeline-indicator-sky-ring: oklch(74.6% 0.16 232.661 / 0.3);
  --zui-timeline-indicator-rose-border: oklch(64.5% 0.246 16.439 / 0.6);
  --zui-timeline-indicator-rose-bg: oklch(64.5% 0.246 16.439 / 0.2);
  --zui-timeline-indicator-rose-fg: oklch(41% 0.159 10.272);
  --zui-timeline-indicator-rose-ring: oklch(71.2% 0.194 13.428 / 0.3);
  --zui-timeline-indicator-purple-border: oklch(62.7% 0.265 303.9 / 0.6);
  --zui-timeline-indicator-purple-bg: oklch(62.7% 0.265 303.9 / 0.2);
  --zui-timeline-indicator-purple-fg: oklch(38.1% 0.176 304.987);
  --zui-timeline-indicator-purple-ring: oklch(71.4% 0.203 305.504 / 0.3);
  --zui-timeline-indicator-pink-border: oklch(65.6% 0.241 354.308 / 0.6);
  --zui-timeline-indicator-pink-bg: oklch(65.6% 0.241 354.308 / 0.2);
  --zui-timeline-indicator-pink-fg: oklch(40.8% 0.153 2.432);
  --zui-timeline-indicator-pink-ring: oklch(71.8% 0.202 349.761 / 0.3);
  --zui-timeline-indicator-orange-border: oklch(70.5% 0.213 47.604 / 0.6);
  --zui-timeline-indicator-orange-bg: oklch(70.5% 0.213 47.604 / 0.2);
  --zui-timeline-indicator-orange-fg: oklch(40.8% 0.123 38.172);
  --zui-timeline-indicator-orange-ring: oklch(75% 0.183 55.934 / 0.3);
  --zui-timeline-indicator-yellow-border: oklch(79.5% 0.184 86.047 / 0.6);
  --zui-timeline-indicator-yellow-bg: oklch(79.5% 0.184 86.047 / 0.2);
  --zui-timeline-indicator-yellow-fg: oklch(42.1% 0.095 57.708);
  --zui-timeline-indicator-yellow-ring: oklch(85.2% 0.199 91.936 / 0.3);
  --zui-timeline-indicator-teal-border: oklch(70.4% 0.14 182.503 / 0.6);
  --zui-timeline-indicator-teal-bg: oklch(70.4% 0.14 182.503 / 0.2);
  --zui-timeline-indicator-teal-fg: oklch(38.6% 0.063 188.416);
  --zui-timeline-indicator-teal-ring: oklch(77.7% 0.152 181.912 / 0.3);
  --zui-timeline-indicator-indigo-border: oklch(58.5% 0.233 277.117 / 0.6);
  --zui-timeline-indicator-indigo-bg: oklch(58.5% 0.233 277.117 / 0.2);
  --zui-timeline-indicator-indigo-fg: oklch(35.9% 0.144 278.697);
  --zui-timeline-indicator-indigo-ring: oklch(67.3% 0.182 276.935 / 0.3);
  --zui-timeline-indicator-emerald-border: oklch(69.6% 0.17 162.48 / 0.6);
  --zui-timeline-indicator-emerald-bg: oklch(69.6% 0.17 162.48 / 0.2);
  --zui-timeline-indicator-emerald-fg: oklch(37.8% 0.077 168.94);
  --zui-timeline-indicator-emerald-ring: oklch(76.5% 0.177 163.223 / 0.3);
  --zui-timeline-indicator-gray-border: oklch(55.1% 0.027 264.364 / 0.6);
  --zui-timeline-indicator-gray-bg: oklch(55.1% 0.027 264.364 / 0.2);
  --zui-timeline-indicator-gray-fg: oklch(21% 0.034 264.665);
  --zui-timeline-indicator-gray-ring: oklch(70.7% 0.022 261.325 / 0.3);
  --zui-timeline-indicator-violet-border: oklch(60.6% 0.25 292.717 / 0.6);
  --zui-timeline-indicator-violet-bg: oklch(60.6% 0.25 292.717 / 0.2);
  --zui-timeline-indicator-violet-fg: oklch(38% 0.189 293.745);
  --zui-timeline-indicator-violet-ring: oklch(70.2% 0.183 293.541 / 0.3);
  --zui-timeline-indicator-gradient-blue-from: oklch(62.3% 0.214 259.815);
  --zui-timeline-indicator-gradient-blue-to: oklch(54.6% 0.245 262.881);
  --zui-timeline-indicator-gradient-blue-fg: #ffffff;
  --zui-timeline-indicator-gradient-blue-ring: oklch(70.7% 0.165 254.624 / 0.3);
  --zui-timeline-indicator-gradient-green-from: oklch(72.3% 0.219 149.579);
  --zui-timeline-indicator-gradient-green-to: oklch(62.7% 0.194 149.214);
  --zui-timeline-indicator-gradient-green-fg: #ffffff;
  --zui-timeline-indicator-gradient-green-ring: oklch(79.2% 0.209 151.711 / 0.3);
  --zui-timeline-indicator-gradient-red-from: oklch(63.7% 0.237 25.331);
  --zui-timeline-indicator-gradient-red-to: oklch(57.7% 0.245 27.325);
  --zui-timeline-indicator-gradient-red-fg: #ffffff;
  --zui-timeline-indicator-gradient-red-ring: oklch(70.4% 0.191 22.216 / 0.3);
  --zui-timeline-indicator-gradient-yellow-from: oklch(85.2% 0.199 91.936);
  --zui-timeline-indicator-gradient-yellow-to: oklch(79.5% 0.184 86.047);
  --zui-timeline-indicator-gradient-yellow-fg: oklch(42.1% 0.095 57.708);
  --zui-timeline-indicator-gradient-yellow-ring: oklch(85.2% 0.199 91.936 / 0.3);
  --zui-timeline-indicator-gradient-purple-from: oklch(71.4% 0.203 305.504);
  --zui-timeline-indicator-gradient-purple-to: oklch(62.7% 0.265 303.9);
  --zui-timeline-indicator-gradient-purple-fg: #ffffff;
  --zui-timeline-indicator-gradient-purple-ring: oklch(71.4% 0.203 305.504 / 0.3);
  --zui-timeline-indicator-gradient-teal-from: oklch(77.7% 0.152 181.912);
  --zui-timeline-indicator-gradient-teal-to: oklch(70.4% 0.14 182.503);
  --zui-timeline-indicator-gradient-teal-fg: #ffffff;
  --zui-timeline-indicator-gradient-teal-ring: oklch(77.7% 0.152 181.912 / 0.3);
  --zui-timeline-indicator-gradient-indigo-from: oklch(67.3% 0.182 276.935);
  --zui-timeline-indicator-gradient-indigo-to: oklch(58.5% 0.233 277.117);
  --zui-timeline-indicator-gradient-indigo-fg: #ffffff;
  --zui-timeline-indicator-gradient-indigo-ring: oklch(67.3% 0.182 276.935 / 0.3);
  --zui-timeline-indicator-gradient-pink-from: oklch(71.8% 0.202 349.761);
  --zui-timeline-indicator-gradient-pink-to: oklch(65.6% 0.241 354.308);
  --zui-timeline-indicator-gradient-pink-fg: #ffffff;
  --zui-timeline-indicator-gradient-pink-ring: oklch(71.8% 0.202 349.761 / 0.3);
  --zui-timeline-indicator-gradient-orange-from: oklch(75% 0.183 55.934);
  --zui-timeline-indicator-gradient-orange-to: oklch(70.5% 0.213 47.604);
  --zui-timeline-indicator-gradient-orange-fg: #ffffff;
  --zui-timeline-indicator-gradient-orange-ring: oklch(75% 0.183 55.934 / 0.3);
  --zui-timeline-indicator-blue-border: #2563eb;
  --zui-timeline-indicator-blue-bg: #2563eb14;
  --zui-timeline-indicator-blue-fg: #2563eb;
  --zui-timeline-indicator-blue-ring: #2563eb33;
  --zui-timeline-indicator-cyan-border: #0891b2;
  --zui-timeline-indicator-cyan-bg: #0891b214;
  --zui-timeline-indicator-cyan-fg: #0891b2;
  --zui-timeline-indicator-cyan-ring: #0891b233;
  --zui-timeline-indicator-green-border: #16a34a;
  --zui-timeline-indicator-green-bg: #16a34a14;
  --zui-timeline-indicator-green-fg: #16a34a;
  --zui-timeline-indicator-green-ring: #16a34a33;
  --zui-timeline-indicator-lime-border: #65a30d;
  --zui-timeline-indicator-lime-bg: #65a30d14;
  --zui-timeline-indicator-lime-fg: #65a30d;
  --zui-timeline-indicator-lime-ring: #65a30d33;
  --zui-timeline-indicator-mint-border: #10b981;
  --zui-timeline-indicator-mint-bg: #10b98114;
  --zui-timeline-indicator-mint-fg: #10b981;
  --zui-timeline-indicator-mint-ring: #10b98133;
  --zui-timeline-indicator-ocean-border: #0284c7;
  --zui-timeline-indicator-ocean-bg: #0284c714;
  --zui-timeline-indicator-ocean-fg: #0284c7;
  --zui-timeline-indicator-ocean-ring: #0284c733;
  --zui-timeline-indicator-sapphire-border: #1d4ed8;
  --zui-timeline-indicator-sapphire-bg: #1d4ed814;
  --zui-timeline-indicator-sapphire-fg: #1d4ed8;
  --zui-timeline-indicator-sapphire-ring: #1d4ed833;
  --zui-timeline-indicator-lavender-border: #8b5cf6;
  --zui-timeline-indicator-lavender-bg: #8b5cf614;
  --zui-timeline-indicator-lavender-fg: #8b5cf6;
  --zui-timeline-indicator-lavender-ring: #8b5cf633;
  --zui-timeline-indicator-ruby-border: #be123c;
  --zui-timeline-indicator-ruby-bg: #be123c14;
  --zui-timeline-indicator-ruby-fg: #be123c;
  --zui-timeline-indicator-ruby-ring: #be123c33;
  --zui-timeline-indicator-red-border: #dc2626;
  --zui-timeline-indicator-red-bg: #dc262614;
  --zui-timeline-indicator-red-fg: #dc2626;
  --zui-timeline-indicator-red-ring: #dc262633;
  --zui-timeline-indicator-slate-border: #475569;
  --zui-timeline-indicator-slate-bg: #47556914;
  --zui-timeline-indicator-slate-fg: #475569;
  --zui-timeline-indicator-slate-ring: #47556933;
  --zui-timeline-indicator-zinc-border: #52525b;
  --zui-timeline-indicator-zinc-bg: #52525b14;
  --zui-timeline-indicator-zinc-fg: #52525b;
  --zui-timeline-indicator-zinc-ring: #52525b33;
  --zui-timeline-indicator-stone-border: #57534e;
  --zui-timeline-indicator-stone-bg: #57534e14;
  --zui-timeline-indicator-stone-fg: #57534e;
  --zui-timeline-indicator-stone-ring: #57534e33;
  --zui-timeline-indicator-royal-border: #4338ca;
  --zui-timeline-indicator-royal-bg: #4338ca14;
  --zui-timeline-indicator-royal-fg: #4338ca;
  --zui-timeline-indicator-royal-ring: #4338ca33;
  --zui-timeline-indicator-electric-border: #0ea5e9;
  --zui-timeline-indicator-electric-bg: #0ea5e914;
  --zui-timeline-indicator-electric-fg: #0ea5e9;
  --zui-timeline-indicator-electric-ring: #0ea5e933;
  --zui-timeline-indicator-forest-border: #166534;
  --zui-timeline-indicator-forest-bg: #16653414;
  --zui-timeline-indicator-forest-fg: #166534;
  --zui-timeline-indicator-forest-ring: #16653433;
  --zui-timeline-indicator-sunset-border: #ea580c;
  --zui-timeline-indicator-sunset-bg: #ea580c14;
  --zui-timeline-indicator-sunset-fg: #ea580c;
  --zui-timeline-indicator-sunset-ring: #ea580c33;
  --zui-timeline-indicator-magenta-border: #c026d3;
  --zui-timeline-indicator-magenta-bg: #c026d314;
  --zui-timeline-indicator-magenta-fg: #c026d3;
  --zui-timeline-indicator-magenta-ring: #c026d333;
  --zui-timeline-indicator-crimson-border: #b91c1c;
  --zui-timeline-indicator-crimson-bg: #b91c1c14;
  --zui-timeline-indicator-crimson-fg: #b91c1c;
  --zui-timeline-indicator-crimson-ring: #b91c1c33;
  --zui-timeline-indicator-aqua-border: #0f766e;
  --zui-timeline-indicator-aqua-bg: #0f766e14;
  --zui-timeline-indicator-aqua-fg: #0f766e;
  --zui-timeline-indicator-aqua-ring: #0f766e33;
  --zui-timeline-indicator-plum-border: #7e22ce;
  --zui-timeline-indicator-plum-bg: #7e22ce14;
  --zui-timeline-indicator-plum-fg: #7e22ce;
  --zui-timeline-indicator-plum-ring: #7e22ce33;
  --zui-timeline-connector: #0000001f;
  --zui-timeline-title-fg: oklch(20.8% 0.042 265.755);
  --zui-timeline-description-fg: oklch(44.6% 0.03 256.802);
}

/* Dark theme variables follow the same names with -dark appended. */
.dark {
  --zui-timeline-indicator-default-fg-dark: oklch(96.7% 0.003 264.542);
  --zui-timeline-indicator-sky-fg-dark: oklch(95.1% 0.026 236.824);
}

Overview

Indicators inherit a themeable appearance and size from the Timeline root, and any item can override its own appearance. Every color is a --zui-timeline-* CSS variable with a paired dark-mode value.

Common use cases

  • Order and shipment tracking.
  • Activity and audit feeds.
  • Product changelogs and release notes.
  • Project milestones and roadmaps.

FAQ

How is the connector line drawn?

Each item except the last renders an absolutely-positioned connector that runs from its indicator down to the next item. The last item drops its bottom padding so the track ends cleanly.

Can the timeline animate on scroll?

Import TimelineItem from the /animated entry to get a staggered fade-and-rise entrance that respects prefers-reduced-motion. The static entry ships without framer-motion.