Roadmap UIRoadmap UI

Gantt

The Gantt chart is a powerful tool for visualizing project schedules and tracking the progress of tasks. It provides a clear, hierarchical view of tasks, allowing you to easily identify manage project timelines.

Issues

Duration

Cloud Infrastructure

Cloud Asset Management

2 months

Real-time Project Analytics

2 months

Global CDN Integration

2 months

Blockchain-based Asset Licensing

about 2 months

Collaboration Tools

Collaborative Editing

6 months

Real-time Video Chat

4 months

Version Control System

about 2 months

Multi-User Permissions

2 months

Collaborative Storyboarding

2 months

Real-time Language Translation

2 months

Core AI Features

AI Scene Analysis

7 months

AI-Powered Color Grading

5 months

AI Voice-to-Text Subtitles

3 months

AI-Assisted Video Transitions

2 months

AI Content-Aware Fill

about 2 months

AI-Powered Audio Enhancement

2 months

AI Scene Recommendations

2 months

AI-Driven Video Compression

2 months

AI Object Tracking

2 months

AI-Powered Video Summarization

2 months

2023

Jan

Feb

Mar

Apr

May

Jun

Jul

Aug

Sep

Oct

Nov

Dec

2024

Jan

Feb

Mar

Apr

May

Jun

Jul

Aug

Sep

Oct

Nov

Dec

2025

Jan

Feb

Mar

Apr

May

Jun

Jul

Aug

Sep

Oct

Nov

Dec

Project KickoffSep 01, 2024
Phase 1 CompletionOct 31, 2024
Beta ReleaseMar 01, 2025
Version 1.0 LaunchJun 30, 2025
User Feedback ReviewSep 01, 2025
Annual Performance EvaluationDec 31, 2025
TodayDec 02, 2024
Jan 01, 2023

Installation

npx roadmap-ui add gantt

Features

  • Resizable and draggable timeline items
  • Markers to highlight important dates
  • Today marker to highlight the current date
  • Create marker trigger to create a new marker
  • Grouping of features

Code

gantt.tsx
'use client';
 
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuTrigger,
} from '@/components/ui/context-menu';
import { exampleFeatures, exampleMarkers } from '@/lib/content';
import {
  GanttCreateMarkerTrigger,
  GanttFeatureItem,
  GanttFeatureList,
  GanttFeatureListGroup,
  GanttHeader,
  GanttMarker,
  GanttProvider,
  GanttSidebar,
  GanttSidebarGroup,
  GanttSidebarItem,
  GanttTimeline,
  GanttToday,
} from '@/components/roadmap-ui/gantt';
import groupBy from 'lodash.groupby';
import { EyeIcon, LinkIcon, TrashIcon } from 'lucide-react';
import { type FC, useState } from 'react';
import { toast } from 'sonner';
 
export const GanttExample: FC = () => {
  const [features, setFeatures] = useState(exampleFeatures);
 
  const groupedFeatures: Record<string, typeof features> = groupBy(
    features,
    'group.name'
  );
 
  const sortedGroupedFeatures = Object.fromEntries(
    Object.entries(groupedFeatures).sort(([nameA], [nameB]) =>
      nameA.localeCompare(nameB)
    )
  );
 
  const handleViewFeature = (id: string) =>
    toast.success(`Feature selected: ${id}`);
 
  const handleCopyLink = (id: string) => toast.success(`Copy link: ${id}`);
 
  const handleRemoveFeature = (id: string) =>
    setFeatures((prev) => prev.filter((feature) => feature.id !== id));
 
  const handleRemoveMarker = (id: string) =>
    toast.success(`Remove marker: ${id}`);
 
  const handleCreateMarker = (date: Date) =>
    toast.success(`Create marker: ${date.toISOString()}`);
 
  const handleMoveFeature = (id: string, startAt: Date, endAt: Date | null) => {
    if (!endAt) {
      return;
    }
 
    setFeatures((prev) =>
      prev.map((feature) =>
        feature.id === id ? { ...feature, startAt, endAt } : feature
      )
    );
 
    toast.success(`Move feature: ${id} from ${startAt} to ${endAt}`);
  };
 
  const handleAddFeature = (date: Date) =>
    toast.success(`Add feature: ${date.toISOString()}`);
 
  return (
    <GanttProvider onAddItem={handleAddFeature} range="monthly" zoom={100}>
      <GanttSidebar>
        {Object.entries(sortedGroupedFeatures).map(([group, features]) => (
          <GanttSidebarGroup key={group} name={group}>
            {features.map((feature) => (
              <GanttSidebarItem
                key={feature.id}
                feature={feature}
                onSelectItem={handleViewFeature}
              />
            ))}
          </GanttSidebarGroup>
        ))}
      </GanttSidebar>
      <GanttTimeline>
        <GanttHeader />
        <GanttFeatureList>
          {Object.entries(sortedGroupedFeatures).map(([group, features]) => (
            <GanttFeatureListGroup key={group}>
              {features.map((feature) => (
                <div className="flex" key={feature.id}>
                  <ContextMenu>
                    <ContextMenuTrigger asChild>
                      <button
                        type="button"
                        onClick={() => handleViewFeature(feature.id)}
                      >
                        <GanttFeatureItem
                          onMove={handleMoveFeature}
                          {...feature}
                        >
                          <p className="flex-1 truncate text-xs">
                            {feature.name}
                          </p>
                          {feature.owner && (
                            <Avatar className="h-4 w-4">
                              <AvatarImage src={feature.owner.image} />
                              <AvatarFallback>
                                {feature.owner.name?.slice(0, 2)}
                              </AvatarFallback>
                            </Avatar>
                          )}
                        </GanttFeatureItem>
                      </button>
                    </ContextMenuTrigger>
                    <ContextMenuContent>
                      <ContextMenuItem
                        className="flex items-center gap-2"
                        onClick={() => handleViewFeature(feature.id)}
                      >
                        <EyeIcon size={16} className="text-muted-foreground" />
                        View feature
                      </ContextMenuItem>
                      <ContextMenuItem
                        className="flex items-center gap-2"
                        onClick={() => handleCopyLink(feature.id)}
                      >
                        <LinkIcon size={16} className="text-muted-foreground" />
                        Copy link
                      </ContextMenuItem>
                      <ContextMenuItem
                        className="flex items-center gap-2 text-destructive"
                        onClick={() => handleRemoveFeature(feature.id)}
                      >
                        <TrashIcon size={16} />
                        Remove from roadmap
                      </ContextMenuItem>
                    </ContextMenuContent>
                  </ContextMenu>
                </div>
              ))}
            </GanttFeatureListGroup>
          ))}
        </GanttFeatureList>
        {exampleMarkers.map((marker) => (
          <GanttMarker
            key={marker.id}
            {...marker}
            onRemove={handleRemoveMarker}
          />
        ))}
        <GanttToday />
        <GanttCreateMarkerTrigger onCreateMarker={handleCreateMarker} />
      </GanttTimeline>
    </GanttProvider>
  );
};

Subcomponents

The Gantt chart is made up of the following subcomponents.

GanttProvider

The GanttProvider component is the root component of the Gantt chart. It contains the drag-and-drop context and provides the necessary context for the other components.

PropTypeDefault
range
Range
-
zoom
number
-
onAddItem
(date: Date) => void
-
children
ReactNode
-
className
string
-

GanttCreateMarkerTrigger

The GanttCreateMarkerTrigger component is a button that triggers the creation of a new marker.

PropTypeDefault
onCreateMarker
(date: Date) => void
-
className
string
-

GanttFeatureItem

The GanttFeatureItem component is a single feature in the Gantt chart.

PropTypeDefault
id
string
-
name
string
-
startAt
Date
-
endAt
Date
-
status
GanttStatus
-
onMove
(id: string, startDate: Date, endDate: Date | null) => void
-
children
ReactNode
-
className
string
-

GanttFeatureList

The GanttFeatureList component is a container for the features in the Gantt chart.

PropTypeDefault
className
string
-
children
ReactNode
-

GanttFeatureListGroup

The GanttFeatureListGroup component is a container for a group of features in the Gantt chart.

PropTypeDefault
children
ReactNode
-
className
string
-

GanttSidebar

The GanttSidebar component is a container for the sidebar in the Gantt chart.

PropTypeDefault
children
ReactNode
-
className
string
-

GanttSidebarGroup

The GanttSidebarGroup component is a container for a group of items in the sidebar.

PropTypeDefault
children
ReactNode
-
name
string
-
className
string
-

GanttSidebarItem

The GanttSidebarItem component is a single item in the sidebar.

PropTypeDefault
feature
GanttFeature
-
onSelectItem
(id: string) => void
-
className
string
-

GanttTimeline

The GanttTimeline component is a container for the timeline in the Gantt chart.

PropTypeDefault
children
ReactNode
-
className
string
-

GanttMarker

The GanttMarker component is a single marker in the Gantt chart.

PropTypeDefault
id
string
-
date
Date
-
label
string
-

GanttHeader

The GanttHeader component is the header of the Gantt chart.

PropTypeDefault
className
string
-

On this page