npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

gantt-lib

v0.103.0

Published

Lightweight React Gantt chart component library

Downloads

5,107

Readme

gantt-lib

Demo

Screenshot

Lightweight React Gantt chart component library with drag-and-drop task management.

Features

  • 📊 Interactive Gantt chart with drag-and-drop task management
  • 🎨 Customizable via CSS variables
  • 📅 Multi-month calendar grid with two-row header (month + day)
  • 🌈 Weekend highlighting with customizable colors
  • 📍 Today indicator vertical line
  • 📈 Progress bars with accepted/completed states
  • Performance optimized for ~100 tasks at 60fps
  • 📦 Tree-shakeable ESM + CJS builds
  • TypeScript types included

Installation

npm install gantt-lib

Quick Start

import { GanttChart, type Task } from "gantt-lib";
import "gantt-lib/styles.css";

const tasks: Task[] = [
  {
    id: "1",
    name: "Project Kickoff",
    startDate: "2026-02-01",
    endDate: "2026-02-05",
    color: "#10b981",
  },
  {
    id: "2",
    name: "Development",
    startDate: "2026-02-06",
    endDate: "2026-02-20",
  },
];

export default function App() {
  const handleChange = (updated: Task[] | ((prev: Task[]) => Task[])) => {
    // Handle task updates
    setTasks(updated);
  };

  return (
    <GanttChart
      tasks={tasks}
      dayWidth={30}
      rowHeight={36}
      onChange={handleChange}
    />
  );
}

Resource Planner Mode

Use mode="resource-planner" when the primary rows are people, equipment, rooms, or other resources instead of tasks. Omitted mode still renders the default task Gantt chart.

import {
  GanttChart,
  ResourceTimelineChart,
  type ResourceTimelineResource,
} from "gantt-lib";
import "gantt-lib/styles.css";

const resources: ResourceTimelineResource[] = [
  {
    id: "designer",
    name: "Designer",
    items: [
      {
        id: "assignment-1",
        resourceId: "designer",
        title: "Landing page",
        subtitle: "Client A",
        startDate: "2026-04-01",
        endDate: "2026-04-03",
        color: "#2563eb",
      },
    ],
  },
];

export default function Planner() {
  return (
    <GanttChart
      mode="resource-planner"
      resources={resources}
      disableResourceReassignment
      onResourceItemMove={(move) => {
        // Validate authorization/conflicts, then update your resource state.
        console.log(move.itemId, move.fromResourceId, move.toResourceId);
      }}
    />
  );
}

ResourceTimelineChart is also exported for consumers who want the specialized renderer directly. Resource mode does not render task list editing, dependency lines, hierarchy/cascade scheduling, or task reorder behavior.

See the full guide: Resource Planner Mode.

API

GanttChart

Main component that renders the interactive Gantt chart.

| Prop | Type | Default | Description | | ----------------------- | --------------------------------------------- | ---------- | ------------------------------------------------------- | | tasks | Task[] | required | Array of tasks to display | | dayWidth | number | 40 | Width of each day column in pixels | | rowHeight | number | 40 | Height of each task row in pixels | | headerHeight | number | 40 | Height of the header row in pixels | | containerHeight | number | 600 | Container height for vertical scrolling | | onChange | (tasks: Task[] \| Task[] => Task[]) => void | required | Callback when tasks are modified | | enableAutoSchedule | boolean | false | Enable automatic shifting of dependent tasks when predecessor moves (cascade) | | onCascade | (tasks: Task[]) => void | undefined | Callback when cascade drag completes; receives all shifted tasks including the dragged task | | disableConstraints | boolean | false | Disable dependency constraint checking during drag (allows violations during editing) | | onValidateDependencies| (result: ValidationResult) => void | undefined | Callback for dependency validation results (cycles, missing tasks, constraint violations) |

Task

interface Task {
  id: string;
  name: string;
  startDate: string; // ISO date format: YYYY-MM-DD
  endDate: string; // ISO date format: YYYY-MM-DD
  color?: string; // Optional bar color (CSS color value)
  progress?: number; // Optional progress 0–100. Renders a progress bar overlay inside the task bar.
  accepted?: boolean; // Optional. Only meaningful when progress is 100. true = green bar, false/undefined = yellow bar.
  dependencies?: TaskDependency[]; // Optional array of predecessor dependencies
}

Dependencies

Tasks can have dependencies on predecessor tasks using 4 link types following PM standards:

  • FS (Finish-to-Start): Predecessor must finish before successor starts. This is the most common dependency type.
  • SS (Start-to-Start): Predecessor and successor start simultaneously.
  • FF (Finish-to-Finish): Predecessor and successor finish simultaneously.
  • SF (Start-to-Finish): Predecessor must start before successor can finish.

TaskDependency Interface

interface TaskDependency {
  taskId: string;      // ID of predecessor task
  type: 'FS' | 'SS' | 'FF' | 'SF';
  lag?: number;        // Days delay (default: 0); FS lag is clamped to >= 0
}

Lag

  • Positive lag: Delays the successor (e.g., lag: 2 means successor starts 2 days after constraint is satisfied)
  • Negative lag: Allowed for SS/FF/SF links. FS negative lag is reset to 0 to prevent predecessor/successor overlap.

Example

const tasks: Task[] = [
  {
    id: "1",
    name: "Foundation",
    startDate: "2026-02-01",
    endDate: "2026-02-10",
  },
  {
    id: "2",
    name: "Construction",
    startDate: "2026-02-11",
    endDate: "2026-02-25",
    dependencies: [
      { taskId: "1", type: "FS" }  // Starts after Foundation finishes
    ],
  },
];

Cascade Scheduling

Cascade scheduling automatically shifts dependent tasks when a predecessor task is moved or resized. This ensures dependency relationships remain valid during editing.

  • enableAutoSchedule: Enable cascade scheduling by setting this prop to true
  • onCascade: Callback that receives all shifted tasks (including the dragged task) when cascade completes
  • Hard mode: Dependency constraints are enforced during drag (default). Tasks cannot violate dependencies.
  • Soft mode: Set disableConstraints to true to allow violations during editing; lag values are recalculated on completion

Example with cascade scheduling enabled:

<GanttChart
  tasks={tasks}
  enableAutoSchedule={true}
  onCascade={(shiftedTasks) => {
    console.log(`${shiftedTasks.length} tasks were shifted`);
  }}
  onChange={handleChange}
/>

Dependency Examples

Simple FS Dependency

The most common dependency type - successor starts after predecessor finishes:

{
  id: "framing",
  name: "Framing",
  startDate: "2026-02-01",
  endDate: "2026-02-10",
},
{
  id: "roofing",
  name: "Roofing",
  startDate: "2026-02-11",
  endDate: "2026-02-20",
  dependencies: [
    { taskId: "framing", type: "FS" }  // Starts after framing ends
  ],
}

SS with Negative Lag (Overlap)

Start-to-Start dependency allows tasks to overlap. Negative lag pulls the successor start earlier:

{
  id: "plumbing",
  name: "Plumbing",
  startDate: "2026-02-10",
  endDate: "2026-02-20",
  dependencies: [
    { taskId: "framing", type: "SS", lag: -3 }  // Start 3 days before framing ends
  ],
}

Multiple Dependencies

A task can wait for multiple predecessors to complete:

{
  id: "inspection",
  name: "Final Inspection",
  startDate: "2026-02-25",
  endDate: "2026-02-26",
  dependencies: [
    { taskId: "plumbing", type: "FS" },
    { taskId: "electrical", type: "FS" },
    { taskId: "roofing", type: "FF", lag: 2 },  // Finish 2 days after roofing
  ],
}

Mixed Link Types

Different relationship types for complex scheduling:

{
  id: "painting",
  name: "Painting",
  startDate: "2026-02-15",
  endDate: "2026-02-25",
  dependencies: [
    { taskId: "drywall", type: "SS", lag: 2 },      // Start 2 days after drywall starts
    { taskId: "priming", type: "FS" },              // Start after priming finishes
  ],
}

Dependency Validation

The library automatically validates dependencies and detects issues:

  • Cycles: Circular dependencies (A -> B -> A) are detected and highlighted in red
  • Missing tasks: References to non-existent task IDs are reported
  • Constraint violations: When tasks violate their dependencies during drag

Use the onValidateDependencies callback to handle validation results:

<GanttChart
  tasks={tasks}
  onValidateDependencies={(result) => {
    if (!result.isValid) {
      result.errors.forEach(error => {
        console.error(`Task ${error.taskId}: ${error.message}`);
      });
    }
  }}
/>

ValidationResult Interface

interface ValidationResult {
  isValid: boolean;
  errors: DependencyError[];
}

interface DependencyError {
  type: 'cycle' | 'constraint' | 'missing-task';
  taskId: string;
  message: string;
  relatedTaskIds?: string[];
}

Customization

CSS Variables

Override these CSS variables to customize the appearance:

:root {
  /* Grid Colors */
  --gantt-grid-line-color: #e0e0e0;
  --gantt-cell-background: #ffffff;
  --gantt-row-hover-background: #f8f9fa;

  /* Dimensions */
  --gantt-row-height: 30px;
  --gantt-header-height: 40px;
  --gantt-day-width: 30px;

  /* Task Bar Styling */
  --gantt-task-bar-default-color: #3b82f6;
  --gantt-task-bar-text-color: #ffffff;
  --gantt-task-bar-border-radius: 4px;
  --gantt-task-bar-height: 24px;

  /* Progress Bar */
  --gantt-progress-color: rgba(0, 0, 0, 0.2); /* In-progress overlay */
  --gantt-progress-completed: #fbbf24; /* 100% but not accepted */
  --gantt-progress-accepted: #22c55e; /* 100% and accepted */

  /* Today Indicator */
  --gantt-today-indicator-color: rgba(255, 0, 0, 0.2);
  --gantt-today-indicator-width: 2px;

  /* Calendar Grid - Weekend */
  --gantt-weekend-background: #fff9f8;
  --gantt-weekend-border: #fca5a5;

  /* Calendar Grid - Separators */
  --gantt-month-separator-width: 2px;
  --gantt-month-separator-color: #a1a1a1;
  --gantt-week-separator-width: 1px;
  --gantt-week-separator-color: #f3f4f6;
  --gantt-day-line-width: 1px;
  --gantt-day-line-color: #f3f4f6;
}

Example: Dark Theme

:root {
  --gantt-cell-background: #1f2937;
  --gantt-grid-line-color: #374151;
  --gantt-task-bar-default-color: #3b82f6;
  --gantt-weekend-background: #374151;
}

Peer Dependencies

  • react >= 18
  • react-dom >= 18

Dependencies

  • date-fns ^4.1.0

License

MIT

GitHub

https://github.com/simon100500/gantt-lib