Timeline

Material Design 3 timeline component for displaying chronological events and milestones

Layout And State Contract

Default, timeline-right (inline-end), timeline-horizontal, and timeline-alternate layouts follow document direction. Alternate timelines become one column below 640px. Horizontal timelines scroll within their container; give overflowing containers a name and tabindex="0" for keyboard access. timeline-compact, timeline-content-card, documented marker colors and timeline-item-active / timeline-item-pending are shipped. Existing item-color and .active state classes remain supported.

Use an ordered list for chronological events and native time values. timeline-collapsible / .expanded are visual hooks only: applications must provide semantic buttons, synchronized ARIA and hidden/inert panels, restoring focus before hiding an active descendant. CSS does not provide a controller.

Timeline

Timelines display a list of events in chronological order, helping users understand the sequence of events and milestones. @duskmoon-dev/core provides a flexible Material Design 3-inspired timeline component.

Basic Usage

Basic Timeline

2 hours ago

Project Started

The project has been initialized and setup is complete.

1 hour ago

First Commit

Initial code structure and dependencies added.

30 minutes ago

Tests Passing

All unit tests are now passing successfully.

Layouts

Vertical Timeline (Default)

The default layout displays events vertically with a connecting line:

Vertical Timeline

January 15, 2025

Planning Phase

Initial project planning and requirements gathering.

February 1, 2025

Development Begins

Started coding the core features.

Horizontal Timeline

Display events horizontally for a different perspective:

Horizontal Timeline

Q1 2025

Phase 1

Initial development

Q2 2025

Phase 2

Feature expansion

Q3 2025

Phase 3

Launch preparation

Alternate Layout (Zigzag)

Create a zigzag pattern with alternating sides:

Alternate Layout Timeline

Step 1

Discovery

Understanding user needs and requirements.

Step 2

Design

Creating wireframes and prototypes.

Step 3

Development

Building the product.

Marker Colors

Use different colors to categorize events or show status:

Timeline with Colored Markers

Now

Primary Event

Default primary color marker.

1 day ago

Secondary Event

Secondary color marker.

2 days ago

Tertiary Event

Tertiary color marker.

3 days ago

Completed Task

Successfully completed milestone.

4 days ago

Error Occurred

An error was detected and resolved.

Accent, Neutral, and Base Markers

Use timeline-marker-accent, timeline-marker-neutral, and timeline-marker-base for semantic marker colors. Accent and neutral use their matching content tokens; base uses base-300 with base-content. Icons can appear on the marker itself or inside it, and nested dots use the matching content color.

Semantic Marker Colors

Featured Event

Accent marker with an icon.

Routine Update

Neutral marker with a nested icon.

Background Event

Base marker with a contrasting dot.

Icon Markers

Add icons to markers for better visual communication:

Timeline with Icon Markers

Completed

Task Finished

The task was completed successfully.

In Progress

New Feature

Working on the new feature implementation.

Verified

Quality Check

All tests passed verification.

Item States

Active/Current State

Highlight the current or active timeline item with a pulsing animation:

Timeline with Active State

Yesterday

Design Complete

All designs approved.

Today

Development in Progress

Currently implementing the features.

Tomorrow

Testing Phase

Scheduled to begin testing.

Pending State

Show future or pending items with reduced opacity:

Timeline with Pending State

Completed

Phase 1 Done

First phase successfully completed.

Upcoming

Phase 2 Pending

Waiting to start the next phase.

Size Variants

Small Timeline

Small Timeline

10:00 AM

Small Event

Compact timeline for tight spaces.

11:00 AM

Another Event

More concise display.

Large Timeline

Large Timeline

January 2025

Major Milestone

Larger timeline for prominent display with more visual impact and better readability.

February 2025

Next Milestone

Enhanced visibility for important events and detailed information.

Compact Timeline

Reduce spacing for more condensed display:

Compact Timeline

08:00

Morning Meeting

Team sync and planning.

10:00

Development

Coding session.

14:00

Code Review

PR review session.

Card Content

Display timeline content in card containers for better separation:

Timeline with Card Content

March 15, 2025

Product Launch

Successfully launched version 1.0 to production. All systems operational and receiving positive user feedback.

March 20, 2025

Feature Update

Added new analytics dashboard and improved performance by 40%.

March 25, 2025

Mobile App Release

iOS and Android apps now available on respective app stores.

Best Practices

Clear Chronological Order

Always display events in chronological order (newest first or oldest first, consistently):

Clear Chronological Order

March 1, 2025

Project Kickoff

March 15, 2025

Milestone 1

March 30, 2025

Current Sprint

Meaningful Time Labels

Use clear, contextual time labels:

Meaningful Time Labels

January 15, 2025 at 2:30 PM

Contract Signed

2 hours ago

Update Deployed

Use Colors Meaningfully

Apply colors to convey status or category:

Meaningful Color Usage

Deployment Successful

Build Failed

In Progress

Accessibility

Ensure timeline content is accessible:

Accessible Timeline

Project Started

Initial project setup and team onboarding completed.

Framework Examples

React

interface TimelineItemProps {
  time: string;
  title: string;
  description: string;
  markerColor?: 'primary' | 'secondary' | 'tertiary' | 'accent' | 'neutral' | 'base' | 'success' | 'error';
  state?: 'active' | 'pending';
  icon?: React.ReactNode;
}

interface TimelineProps {
  items: TimelineItemProps[];
  layout?: 'vertical' | 'horizontal' | 'alternate';
  size?: 'sm' | 'md' | 'lg';
  compact?: boolean;
}

export function Timeline({ items, layout = 'vertical', size, compact }: TimelineProps) {
  const baseClasses = ['timeline'];

  if (layout === 'horizontal') baseClasses.push('timeline-horizontal');
  if (layout === 'alternate') baseClasses.push('timeline-alternate');
  if (size === 'sm') baseClasses.push('timeline-sm');
  if (size === 'lg') baseClasses.push('timeline-lg');
  if (compact) baseClasses.push('timeline-compact');

  return (
    <div className={baseClasses.join(' ')}>
      {items.map((item, index) => (
        <TimelineItem key={index} {...item} />
      ))}
    </div>
  );
}

export function TimelineItem({
  time,
  title,
  description,
  markerColor,
  state,
  icon
}: TimelineItemProps) {
  const itemClasses = ['timeline-item'];
  const markerClasses = ['timeline-marker'];

  if (state === 'active') itemClasses.push('timeline-item-active');
  if (state === 'pending') itemClasses.push('timeline-item-pending');

  if (markerColor) markerClasses.push(`timeline-marker-${markerColor}`);
  if (icon) markerClasses.push('timeline-marker-icon');

  return (
    <div className={itemClasses.join(' ')}>
      <div className={markerClasses.join(' ')}>
        {icon}
      </div>
      <div className="timeline-content">
        <span className="timeline-time">{time}</span>
        <h3 className="timeline-title">{title}</h3>
        <p className="timeline-description">{description}</p>
      </div>
    </div>
  );
}

// Usage
<Timeline
  layout="vertical"
  items={[
    {
      time: '2 hours ago',
      title: 'Project Started',
      description: 'Initial setup complete',
      markerColor: 'success'
    },
    {
      time: '1 hour ago',
      title: 'Development',
      description: 'Working on features',
      state: 'active'
    }
  ]}
/>

Vue

<template>
  <div :class="timelineClasses">
    <div
      v-for="(item, index) in items"
      :key="index"
      :class="itemClasses(item)"
    >
      <div :class="markerClasses(item)">
        <slot :name="`icon-${index}`">{{ item.icon }}</slot>
      </div>
      <div class="timeline-content" :class="{ 'timeline-content-card': item.card }">
        <span class="timeline-time">{{ item.time }}</span>
        <h3 class="timeline-title">{{ item.title }}</h3>
        <p class="timeline-description">{{ item.description }}</p>
      </div>
    </div>
  </div>
</template>

<script setup>
import { computed } from 'vue'

const props = defineProps({
  items: {
    type: Array,
    required: true
  },
  layout: {
    type: String,
    default: 'vertical',
    validator: (value) => ['vertical', 'horizontal', 'alternate'].includes(value)
  },
  size: {
    type: String,
    validator: (value) => ['sm', 'md', 'lg'].includes(value)
  },
  compact: Boolean
})

const timelineClasses = computed(() => {
  const classes = ['timeline']
  if (props.layout === 'horizontal') classes.push('timeline-horizontal')
  if (props.layout === 'alternate') classes.push('timeline-alternate')
  if (props.size === 'sm') classes.push('timeline-sm')
  if (props.size === 'lg') classes.push('timeline-lg')
  if (props.compact) classes.push('timeline-compact')
  return classes
})

const itemClasses = (item) => {
  const classes = ['timeline-item']
  if (item.state === 'active') classes.push('timeline-item-active')
  if (item.state === 'pending') classes.push('timeline-item-pending')
  return classes
}

const markerClasses = (item) => {
  const classes = ['timeline-marker']
  if (item.markerColor) classes.push(`timeline-marker-${item.markerColor}`)
  if (item.icon) classes.push('timeline-marker-icon')
  return classes
}
</script>

<!-- Usage -->
<Timeline
  layout="vertical"
  :items="[
    {
      time: '2 hours ago',
      title: 'Project Started',
      description: 'Initial setup complete',
      markerColor: 'success'
    },
    {
      time: '1 hour ago',
      title: 'Development',
      description: 'Working on features',
      state: 'active'
    }
  ]"
/>

API Reference

Timeline Container Classes

Class Description
.timeline Base timeline container (required)
.timeline-horizontal Horizontal layout
.timeline-alternate Alternating zigzag layout
.timeline-sm Small size variant
.timeline-lg Large size variant
.timeline-compact Compact spacing

Timeline Item Classes

Class Description
.timeline-item Individual timeline item (required)
.timeline-item-active Active/current item with pulsing animation
.timeline-item-pending Pending/future item with reduced opacity

Marker Classes

Class Description
.timeline-marker Timeline marker dot (required)
.timeline-marker-secondary Secondary color marker
.timeline-marker-tertiary Tertiary color marker
.timeline-marker-accent Accent marker with accent content color
.timeline-marker-neutral Neutral marker with neutral content color
.timeline-marker-base Base-300 marker with base content color
.timeline-marker-success Success/green marker
.timeline-marker-error Error/red marker
.timeline-marker-icon Marker with icon content
.timeline-marker-dot Nested dot using the semantic marker content color

Content Classes

Class Description
.timeline-content Content container (required)
.timeline-content-card Card-styled content with border and shadow
.timeline-time Time/date label
.timeline-title Event title
.timeline-description Event description text

Combinations

Combined Timeline Features

...
Q1 2025

Major Release

Version 2.0 launched

Step 1

Initialize

  • Stepper - Step-by-step process indicator
  • Badge - Status indicators
  • Card - Content containers

See Also