Skip to content

MikaStiebitz/React-Modern-Gantt

Repository files navigation

React Modern Gantt

A flexible, customizable Gantt chart component for React applications with drag-and-drop task scheduling, dark mode support, progress tracking, and multiple view modes.

npm version license bundle size

React Modern Gantt in Dark Mode

Live Demo


πŸ“‹ Table of Contents

✨ Features

  • πŸ“Š Interactive timeline with drag-and-drop task scheduling
  • 🎨 Fully customizable with CSS variables and custom classes
  • πŸ•’ Multiple view modes (Day, Week, Month, Quarter, Year)
  • πŸŒ™ Dark mode support built-in
  • πŸ“± Responsive design that works across devices
  • πŸ“ˆ Progress tracking with visual indicators and interactive updates
  • πŸ”„ Task dependencies and relationship management
  • 🎯 Event handling for clicks, updates, selections
  • 🧩 Composable API with extensive custom render props for advanced customization
  • 🌊 Smooth animations with configurable speeds and thresholds
  • πŸ”„ Auto-scrolling during drag operations

πŸ“¦ Installation

NPM

npm install react-modern-gantt

Yarn

yarn add react-modern-gantt

πŸš€ Quick Start

import React, { useState } from "react";
import GanttChart from "react-modern-gantt";
// ⚠️ IMPORTANT: Don't forget to import the styles!
import "react-modern-gantt/dist/index.css";

function App() {
    const [tasks, setTasks] = useState([
        {
            id: "team-1",
            name: "Engineering",
            description: "Development Team",
            tasks: [
                {
                    id: "task-1",
                    name: "Website Redesign",
                    startDate: new Date(2023, 0, 1),
                    endDate: new Date(2023, 2, 15),
                    color: "#3b82f6",
                    percent: 75,
                },
                // More tasks...
            ],
        },
        // More groups...
    ]);

    const handleTaskUpdate = (groupId, updatedTask) => {
        setTasks(prevTasks =>
            prevTasks.map(group =>
                group.id === groupId
                    ? {
                          ...group,
                          tasks: group.tasks.map(task => (task.id === updatedTask.id ? updatedTask : task)),
                      }
                    : group
            )
        );
    };

    return <GanttChart tasks={tasks} onTaskUpdate={handleTaskUpdate} darkMode={false} showProgress={true} />;
}

πŸ“Œ Note: Make sure to import the CSS file to apply all necessary styles: import "react-modern-gantt/dist/index.css"; Without this import, the component will not be styled correctly.

Using CSS styles

The Gantt chart requires CSS styles that are shipped separately from the component code. You have two options:

Option 1: Import CSS file (Recommended)

// In your application entry point (e.g., App.js or index.js)
import "react-modern-gantt/dist/index.css";

Option 2: Reference CSS in HTML

<!-- In your HTML file -->
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/index.css" />

🧩 Components

Main Components

  • GanttChart: The main component for rendering a Gantt chart
  • TaskItem: Individual task bars
  • TaskList: The left sidebar with task groups
  • Timeline: The header timeline display
  • ViewModeSelector: Controls for switching between timeline views

Utility Components

  • Tooltip: Information tooltip for tasks
  • TodayMarker: Vertical line indicating the current date

πŸ“Š Task & TaskGroup Data Structure

interface Task {
    id: string; // Unique identifier
    name: string; // Task name
    startDate: Date; // Start date
    endDate: Date; // End date
    color?: string; // Task color (CSS color value or hex code)
    percent?: number; // Completion percentage (0-100)
    dependencies?: string[]; // IDs of dependent tasks
    [key: string]: any; // Additional custom properties
}

interface TaskGroup {
    id: string; // Unique identifier
    name: string; // Group name
    description?: string; // Group description
    icon?: string; // Optional icon (HTML string)
    tasks: Task[]; // Array of tasks in this group
    [key: string]: any; // Additional custom properties
}

πŸ•’ View Modes

The component supports five different view modes to adapt to different timeline needs:

View Mode Description Best Used For
DAY Shows days Detailed short-term planning (days/weeks)
WEEK Shows weeks Short to medium-term planning (weeks/months)
MONTH Shows months Medium-term planning (months/quarters)
QUARTER Shows quarters Medium to long-term planning (quarters/year)
YEAR Shows years Long-term planning (years)
import { GanttChart, ViewMode } from "react-modern-gantt";

// Using string literals
<GanttChart tasks={tasks} viewMode="day" />

// Using the ViewMode enum
<GanttChart tasks={tasks} viewMode={ViewMode.DAY} />

🎨 Customization

CSS Variables

The easiest way to customize the appearance is by overriding CSS variables:

:root {
    /* Primary colors */
    --rmg-bg-color: #f8f9fb;
    --rmg-text-color: #1a202c;
    --rmg-border-color: #e2e8f0;
    --rmg-task-color: #3182ce;
    --rmg-task-text-color: white;
    --rmg-marker-color: #e53e3e;

    /* Size variables */
    --rmg-row-height: 50px;
    --rmg-task-height: 36px;
    --rmg-border-radius: 6px;

    /* Animation speed */
    --rmg-animation-speed: 0.25;
}

Custom Styles

<GanttChart
    tasks={tasks}
    styles={{
        container: "my-gantt-container",
        title: "my-gantt-title",
        taskList: "my-task-list",
        timeline: "my-timeline",
        todayMarker: "my-today-marker",
        taskRow: "my-task-row",
        tooltip: "my-tooltip",
    }}
    onTaskUpdate={handleTaskUpdate}
/>

Custom Rendering

<GanttChart
    tasks={tasks}
    renderTask={({ task, leftPx, widthPx, topPx, isHovered, isDragging, showProgress }) => (
        <div
            className="my-custom-task"
            style={{
                position: "absolute",
                left: `${leftPx}px`,
                width: `${widthPx}px`,
                top: `${topPx}px`,
                backgroundColor: task.color || "#3182ce",
            }}>
            <div className="my-task-label">{task.name}</div>
            {showProgress && (
                <div className="my-progress-bar">
                    <div className="my-progress-fill" style={{ width: `${task.percent || 0}%` }} />
                </div>
            )}
        </div>
    )}
/>

🎯 Event Handling

Handle various interactions with the Gantt chart:

<GanttChart
    tasks={tasks}
    onTaskUpdate={(groupId, updatedTask) => {
        console.log(`Task ${updatedTask.id} updated in group ${groupId}`);
        // Update your state here
        updateTasks(groupId, updatedTask);
    }}
    onTaskClick={(task, group) => {
        console.log(`Task ${task.id} clicked in group ${group.id}`);
        // Do something when a task is clicked
        selectTask(task.id);
    }}
    onTaskSelect={(task, isSelected) => {
        console.log(`Task ${task.id} selection state: ${isSelected}`);
        // Handle selection state changes
    }}
    onGroupClick={group => {
        console.log(`Group ${group.id} clicked`);
        // Do something when a group is clicked
    }}
    onViewModeChange={viewMode => {
        console.log(`View mode changed to: ${viewMode}`);
        // Handle view mode changes
    }}
/>

πŸŒ™ Dark Mode

Dark mode is built-in and easy to enable:

<GanttChart tasks={tasks} darkMode={true} onTaskUpdate={handleTaskUpdate} />

πŸ”„ Advanced Examples

Custom Task Rendering by Status

<GanttChart
    tasks={tasks}
    getTaskColor={({ task }) => {
        // Task is complete
        if (task.percent === 100) {
            return {
                backgroundColor: "#22c55e", // Green
                borderColor: "#166534",
                textColor: "#ffffff",
            };
        }

        // Task has dependencies
        if (task.dependencies?.length > 0) {
            return {
                backgroundColor: "#f59e0b", // Orange
                textColor: "#ffffff",
            };
        }

        // High priority task
        if (task.priority === "high") {
            return {
                backgroundColor: "#ef4444", // Red
                textColor: "#ffffff",
            };
        }

        // Default color
        return {
            backgroundColor: "#3b82f6", // Blue
            textColor: "#ffffff",
        };
    }}
/>

Custom Tooltip for Detailed Information

<GanttChart
    tasks={tasks}
    renderTooltip={({ task, position, dragType, startDate, endDate }) => (
        <div className="custom-tooltip">
            <h3>{task.name}</h3>

            {dragType && (
                <div className="drag-indicator">{dragType === "move" ? "Moving task..." : "Resizing task..."}</div>
            )}

            <div className="date-range">
                {format(startDate, "MMM d, yyyy")} - {format(endDate, "MMM d, yyyy")}
            </div>

            <div className="progress-section">
                <div className="progress-label">Progress: {task.percent || 0}%</div>
                <div className="progress-bar">
                    <div className="progress-fill" style={{ width: `${task.percent || 0}%` }} />
                </div>
            </div>

            {task.assignee && <div className="assignee">Assigned to: {task.assignee}</div>}
        </div>
    )}
/>

🌐 Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)

❓ FAQ

Can I change the date format in the timeline?

Yes, you can use the locale prop to change the date formatting:

<GanttChart
    tasks={tasks}
    locale="de-DE" // For German formatting
/>

How do I handle updates to tasks?

The Gantt chart is a controlled component, so updates are handled through the onTaskUpdate callback:

const handleTaskUpdate = (groupId, updatedTask) => {
    setTasks(prevTasks =>
        prevTasks.map(group =>
            group.id === groupId
                ? {
                      ...group,
                      tasks: group.tasks.map(task => (task.id === updatedTask.id ? updatedTask : task)),
                  }
                : group
        )
    );
};

Can I make the Gantt chart read-only?

Yes, set the editMode prop to false:

<GanttChart tasks={tasks} editMode={false} />

How do I disable progress indicators?

Set the showProgress prop to false:

<GanttChart tasks={tasks} showProgress={false} />

Can I customize the visual appearance of specific tasks?

Yes, use the getTaskColor function:

<GanttChart
    tasks={tasks}
    getTaskColor={({ task }) => ({
        backgroundColor: task.isUrgent ? "#ef4444" : "#3b82f6",
        textColor: "white",
    })}
/>

Why are my styles not loading?

If your Gantt chart appears without styling, make sure you've imported the CSS file:

import "react-modern-gantt/dist/index.css";

This import should be included in your application's entry point or in the component where you use the Gantt chart.

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.