Docs
Roadmap Timeline

Roadmap Timeline

A clean, modern product roadmap timeline for SaaS products. Features vertical timeline flow, color-coded status, and smooth animations.

Product Roadmap

See what we've built and what's coming next on our journey

Q1 2024Shipped

Completed March 2024

Platform Launch

Initial release with core features and essential functionality for early adopters.

User authentication and authorization
Dashboard with real-time analytics
API integration framework
Basic reporting tools
Email notifications
Q2 2024Shipped

Completed June 2024

Team Collaboration

Enhanced collaboration features to help teams work together more effectively.

Team workspaces and permissions
Real-time collaboration tools
Commenting and mentions
Activity feed and notifications
Shared templates library
Q3 2024In Progress

In Progress - Expected September 2024

Advanced Analytics

Powerful analytics and insights to help you make data-driven decisions.

Custom dashboards and widgets
Advanced filtering and segmentation
Predictive analytics with AI
Export to multiple formats
Automated reports scheduling
Q4 2024In Progress

Expected December 2024

Enterprise Features

Enterprise-grade security, compliance, and scalability features.

SSO and SAML integration
Advanced security controls
Audit logs and compliance
Custom SLA agreements
Dedicated support channel
Q1 2025Planned

Planned for Q1 2025

AI-Powered Automation

Intelligent automation to streamline workflows and boost productivity.

AI-powered recommendations
Automated workflow builder
Smart data categorization
Natural language queries
Predictive task scheduling
Q2 2025Planned

Planned for Q2 2025

Mobile Applications

Native mobile apps for iOS and Android with offline capabilities.

Native iOS and Android apps
Offline mode with sync
Push notifications
Mobile-optimized workflows
Biometric authentication
Q3 2025Planned

Planned for Q3 2025

Global Expansion

Multi-language support and regional data centers for global reach.

Multi-language interface
Regional data centers
Currency and timezone support
Localized content
Compliance with regional laws
Q4 2025Planned

Planned for Q4 2025

Performance & Scale

Infrastructure improvements for lightning-fast performance at any scale.

10x faster load times
Support for 1M+ users
Advanced caching layer
Real-time data streaming
99.99% uptime SLA

2

Shipped

2

In Progress

4

Planned

Installation

Install dependencies

npm install framer-motion lucide-react

Copy and paste the following code into your project.

"use client";
 
import React from "react";
import { motion } from "framer-motion";
import { Check, Clock, Sparkles, ArrowRight } from "lucide-react";
 
interface RoadmapItem {
  id: string;
  quarter: string;
  title: string;
  description: string;
  status: "completed" | "in-progress" | "planned";
  features: string[];
  icon?: React.ElementType;
  date?: string;
}
 
interface RoadmapTimelineProps {
  title?: string;
  description?: string;
  items: RoadmapItem[];
  className?: string;
}
 
export function RoadmapTimeline({
  title = "Product Roadmap",
  description = "See what we're building and what's coming next",
  items,
  className = "",
}: RoadmapTimelineProps) {
  const getStatusConfig = (status: RoadmapItem["status"]) => {
    switch (status) {
      case "completed":
        return {
          label: "Shipped",
          color: "text-emerald-600 dark:text-emerald-400",
          bg: "bg-emerald-50 dark:bg-emerald-950/30",
          border: "border-emerald-200 dark:border-emerald-800",
          dotBg: "bg-emerald-500",
          icon: Check,
        };
      case "in-progress":
        return {
          label: "In Progress",
          color: "text-blue-600 dark:text-blue-400",
          bg: "bg-blue-50 dark:bg-blue-950/30",
          border: "border-blue-200 dark:border-blue-800",
          dotBg: "bg-blue-500",
          icon: Clock,
        };
      case "planned":
        return {
          label: "Planned",
          color: "text-zinc-600 dark:text-zinc-400",
          bg: "bg-zinc-50 dark:bg-zinc-900",
          border: "border-zinc-200 dark:border-zinc-800",
          dotBg: "bg-zinc-400",
          icon: Sparkles,
        };
    }
  };
 
  return (
    <section className={`w-full py-24 ${className}`}>
      <div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
        <motion.div
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.5, ease: "easeOut" }}
          className="mb-16 text-center"
        >
          <h2 className="mb-4 text-4xl font-bold tracking-tight text-zinc-900 dark:text-white sm:text-5xl">
            {title}
          </h2>
          <p className="mx-auto max-w-2xl text-lg text-zinc-600 dark:text-zinc-400">
            {description}
          </p>
        </motion.div>
        <div className="relative space-y-8">
          {items.map((item, index) => {
            const config = getStatusConfig(item.status);
            const StatusIcon = config.icon;
            const ItemIcon = item.icon;
            const isLast = index === items.length - 1;
 
            return (
              <motion.div
                key={item.id}
                initial={{ opacity: 0, x: -20 }}
                animate={{ opacity: 1, x: 0 }}
                transition={{
                  duration: 0.5,
                  delay: index * 0.1,
                  ease: "easeOut",
                }}
                className="relative flex gap-8"
              >
                <div className="relative flex flex-col items-center">
                  <div
                    className={`z-10 flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full border-4 border-white shadow-lg dark:border-zinc-950 ${config.dotBg}`}
                  >
                    <StatusIcon className="h-5 w-5 text-white" />
                  </div>
                  {!isLast && (
                    <div className="absolute top-12 h-full w-0.5 bg-zinc-200 dark:bg-zinc-800" />
                  )}
                </div>
 
                <div className="flex-1 pb-8">
                  <div className="overflow-hidden rounded-2xl border border-zinc-200 bg-white p-6 shadow-sm transition-all duration-300 hover:shadow-md dark:border-zinc-800 dark:bg-zinc-900 sm:p-8">
                    <div className="mb-4 flex flex-wrap items-start justify-between gap-4">
                      <div>
                        <div className="mb-2 flex items-center gap-3">
                          <span className="text-sm font-semibold text-zinc-500 dark:text-zinc-400">
                            {item.quarter}
                          </span>
                          <span
                            className={`inline-flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-semibold ${config.bg} ${config.color}`}
                          >
                            <StatusIcon className="h-3 w-3" />
                            {config.label}
                          </span>
                        </div>
                        {item.date && (
                          <p className="text-xs text-zinc-500 dark:text-zinc-500">
                            {item.date}
                          </p>
                        )}
                      </div>
 
                      {ItemIcon && (
                        <div className="flex h-12 w-12 items-center justify-center rounded-xl bg-zinc-100 dark:bg-zinc-800">
                          {React.createElement(ItemIcon, {
                            className:
                              "h-6 w-6 text-zinc-700 dark:text-zinc-300",
                          })}
                        </div>
                      )}
                    </div>
 
                    <h3 className="mb-2 text-2xl font-bold text-zinc-900 dark:text-white">
                      {item.title}
                    </h3>
                    <p className="mb-6 text-zinc-600 dark:text-zinc-400">
                      {item.description}
                    </p>
                    <div className="grid gap-2 sm:grid-cols-2">
                      {item.features.map((feature, idx) => (
                        <div
                          key={idx}
                          className="flex items-start gap-2 text-sm text-zinc-600 dark:text-zinc-400"
                        >
                          <ArrowRight className="mt-0.5 h-4 w-4 flex-shrink-0 text-zinc-400" />
                          <span>{feature}</span>
                        </div>
                      ))}
                    </div>
                  </div>
                </div>
              </motion.div>
            );
          })}
        </div>
        <motion.div
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.5, delay: 0.4, ease: "easeOut" }}
          className="mt-16 flex flex-wrap justify-center gap-8"
        >
          {[
            {
              status: "completed" as const,
              count: items.filter((i) => i.status === "completed").length,
            },
            {
              status: "in-progress" as const,
              count: items.filter((i) => i.status === "in-progress").length,
            },
            {
              status: "planned" as const,
              count: items.filter((i) => i.status === "planned").length,
            },
          ].map(({ status, count }) => {
            const config = getStatusConfig(status);
            const Icon = config.icon;
            return (
              <div
                key={status}
                className="flex items-center gap-3 rounded-xl border border-zinc-200 bg-white px-6 py-3 dark:border-zinc-800 dark:bg-zinc-900"
              >
                <div
                  className={`flex h-10 w-10 items-center justify-center rounded-lg ${config.bg}`}
                >
                  <Icon className={`h-5 w-5 ${config.color}`} />
                </div>
                <div>
                  <p className="text-2xl font-bold text-zinc-900 dark:text-white">
                    {count}
                  </p>
                  <p className="text-sm text-zinc-600 dark:text-zinc-400">
                    {config.label}
                  </p>
                </div>
              </div>
            );
          })}
        </motion.div>
      </div>
    </section>
  );
}

Features

  • Vertical timeline - Chronological flow from top to bottom
  • Color-coded status - Completed (Green), In Progress (Blue), Planned (Gray)
  • Connected dots - Visual line connecting all milestones
  • Smooth animations - Sequential fade-in transitions
  • Status indicators - Circular dots with status icons
  • Clean cards - Modern card design for each milestone
  • Stats summary - Shows counts by status at bottom
  • Responsive design - Works beautifully on all screen sizes
  • Dark mode ready - Elegant in both themes
  • TypeScript support - Full type safety

Usage

Basic Usage

import RoadmapTimeline from "@/components/ui/roadmap-timeline";
import {Rocket, Users, BarChart3} from "lucide-react";
 
const roadmapItems = [
  {
    id: "q1-2024",
    quarter: "Q1 2024",
    title: "Platform Launch",
    description: "Initial release with core features.",
    status: "completed",
    date: "Completed March 2024",
    icon: Rocket,
    features: ["User authentication", "Dashboard analytics", "API integration"],
  },
  {
    id: "q2-2024",
    quarter: "Q2 2024",
    title: "Team Collaboration",
    description: "Enhanced collaboration features.",
    status: "in-progress",
    date: "Expected June 2024",
    icon: Users,
    features: ["Team workspaces", "Real-time collaboration", "Activity feed"],
  },
  {
    id: "q3-2024",
    quarter: "Q3 2024",
    title: "Advanced Analytics",
    description: "Powerful analytics and insights.",
    status: "planned",
    date: "Planned for Q3 2024",
    icon: BarChart3,
    features: [
      "Custom dashboards",
      "Predictive analytics",
      "Automated reports",
    ],
  },
];
 
export default function Page() {
  return <RoadmapTimeline items={roadmapItems} />;
}

Custom Title and Description

<RoadmapTimeline
  title="Our Journey"
  description="See what we've built and what's coming next"
  items={roadmapItems}
/>

Props

RoadmapTimelineProps

PropTypeDefaultDescription
itemsRoadmapItem[]RequiredArray of roadmap items
titlestring"Product Roadmap"Section title
descriptionstring"See what we're building..."Section description
classNamestring""Additional CSS classes

RoadmapItem

PropTypeRequiredDescription
idstringYesUnique identifier
quarterstringYesQuarter label (e.g., "Q1 2024")
titlestringYesItem title
descriptionstringYesItem description
status"completed" | "in-progress" | "planned"YesCurrent status
featuresstring[]YesList of features
iconReact.ElementTypeNoLucide React icon component
datestringNoDate or timeline info

TypeScript Interface

interface RoadmapItem {
  id: string;
  quarter: string;
  title: string;
  description: string;
  status: "completed" | "in-progress" | "planned";
  features: string[];
  icon?: React.ElementType;
  date?: string;
}
 
interface RoadmapTimelineProps {
  title?: string;
  description?: string;
  items: RoadmapItem[];
  className?: string;
}

Use Cases

Perfect for:

  • Product roadmap pages
  • Feature announcement pages
  • About pages (company timeline)
  • Changelog pages
  • Development progress tracking
  • Investor presentations
  • Customer transparency
  • Team alignment

Customization

Change Colors

// In the component, modify getStatusConfig function
 
case "completed":
  return {
    label: "Shipped",
    color: "text-purple-600 dark:text-purple-400", // Your brand color
    bg: "bg-purple-50 dark:bg-purple-950/30",
    border: "border-purple-200 dark:border-purple-800",
    dotBg: "bg-purple-500",
    icon: Check,
  };

Change Timeline Dot Size

// Modify the dot size
<div className="flex h-16 w-16 items-center justify-center rounded-full">
  {/* Larger: h-16 w-16 */}
  {/* Default: h-12 w-12 */}
  {/* Smaller: h-10 w-10 */}
</div>

Add More Status Types

// Add a new status type
interface RoadmapItem {
  status: "completed" | "in-progress" | "planned" | "cancelled";
  // ...
}
 
// Add to getStatusConfig
case "cancelled":
  return {
    label: "Cancelled",
    color: "text-red-600 dark:text-red-400",
    bg: "bg-red-50 dark:bg-red-950/30",
    border: "border-red-200 dark:border-red-800",
    dotBg: "bg-red-500",
    icon: XCircle,
  };

Change Timeline Line Style

// Make the line thicker
<div className="absolute top-12 h-full w-1 bg-zinc-200" />
 
// Make it dashed
<div className="absolute top-12 h-full w-0.5 border-l-2 border-dashed border-zinc-300" />
 
// Add gradient
<div className="absolute top-12 h-full w-0.5 bg-gradient-to-b from-emerald-500 via-blue-500 to-zinc-300" />

Change Feature Grid Layout

// Show features in single column
<div className="grid gap-2">
  {/* Single column */}
</div>
 
// Show features in 3 columns
<div className="grid gap-2 sm:grid-cols-3">
  {/* 3 columns on larger screens */}
</div>

Remove Stats Summary

// If you don't want the stats at the bottom
// Simply remove or comment out the stats section:
 
{
  /* Stats */
}
{
  /* <motion.div className="mt-16...">
  ...
</motion.div> */
}

Common Patterns

Yearly Roadmap

const roadmap2024 = [
  {
    id: "jan-2024",
    quarter: "January",
    title: "Q1 Features",
    // ...
  },
  {
    id: "apr-2024",
    quarter: "April",
    title: "Q2 Features",
    // ...
  },
];

Company Timeline

const companyTimeline = [
  {
    id: "founded",
    quarter: "2020",
    title: "Company Founded",
    description: "Started with a vision to change the industry.",
    status: "completed",
    icon: Rocket,
    features: [
      "Incorporated in Delaware",
      "Raised seed funding",
      "Hired first employees",
    ],
  },
  {
    id: "series-a",
    quarter: "2022",
    title: "Series A Funding",
    description: "Raised $10M to scale the team.",
    status: "completed",
    icon: TrendingUp,
    features: [
      "Led by Sequoia Capital",
      "Grew team to 50 people",
      "Expanded to 3 countries",
    ],
  },
];

Feature Releases

const featureReleases = [
  {
    id: "v1",
    quarter: "v1.0",
    title: "Initial Release",
    description: "First public version.",
    status: "completed",
    date: "Released Jan 2024",
    icon: Package,
    features: ["Core functionality", "Basic UI", "API v1"],
  },
  {
    id: "v2",
    quarter: "v2.0",
    title: "Major Update",
    description: "Complete redesign and new features.",
    status: "in-progress",
    date: "Expected Mar 2024",
    icon: Sparkles,
    features: ["New UI", "Advanced features", "API v2"],
  },
];

Examples

SaaS Product Roadmap

const saasRoadmap = [
  {
    id: "q1",
    quarter: "Q1 2024",
    title: "Core Platform",
    description: "Essential features for launch.",
    status: "completed",
    icon: Rocket,
    features: [
      "User authentication",
      "Dashboard",
      "API integration",
      "Email notifications",
    ],
  },
  {
    id: "q2",
    quarter: "Q2 2024",
    title: "Team Features",
    description: "Collaboration and team management.",
    status: "in-progress",
    icon: Users,
    features: [
      "Team workspaces",
      "Role-based permissions",
      "Activity feed",
      "Shared templates",
    ],
  },
  {
    id: "q3",
    quarter: "Q3 2024",
    title: "Enterprise",
    description: "Enterprise-grade features.",
    status: "planned",
    icon: Shield,
    features: [
      "SSO integration",
      "Advanced security",
      "Audit logs",
      "Custom SLA",
    ],
  },
];

Mobile App Roadmap

const mobileRoadmap = [
  {
    id: "beta",
    quarter: "Beta",
    title: "Beta Release",
    description: "Limited beta for testing.",
    status: "completed",
    date: "Released Feb 2024",
    icon: TestTube,
    features: ["iOS app", "Core features", "Push notifications"],
  },
  {
    id: "v1",
    quarter: "v1.0",
    title: "Public Launch",
    description: "Full public release.",
    status: "in-progress",
    date: "Expected Apr 2024",
    icon: Smartphone,
    features: ["Android app", "Offline mode", "Widget support"],
  },
];

Analytics Integration

// Track which roadmap items users view
const trackRoadmapView = (itemId: string) => {
  analytics.track("roadmap_item_viewed", {
    item_id: itemId,
    timestamp: Date.now(),
  });
};
 
// Track when users reach the roadmap section
useEffect(() => {
  analytics.track("roadmap_section_viewed");
}, []);

Tips

  1. Update quarterly - Keep your roadmap fresh
  2. Be honest - Transparency builds trust
  3. Show progress - Move items through statuses
  4. Limit scope - Don't show too far ahead
  5. Link to changelog - Connect roadmap to releases
  6. Gather input - Ask users what they want
  7. Celebrate milestones - Highlight achievements