Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelog
  1. Home
  2. Blog
  3. Component guides
  4. React Gantt Chart: Drag, Progress and Dependencies
Auf Deutsch lesen
  1. Blog
  2. Component guides
  3. React Gantt Chart: Drag, Progress and Dependencies
Component guides
Component guides

React Gantt Chart: Drag, Progress and Dependencies

SR
Serban Rusu · Founder of Wingo UI
Oct 19, 2026 · 10 min read

On this page

0%
  1. What should a React Gantt chart component handle?
  2. Is there a free React Gantt chart?
  3. What props does the Wingo UI Gantt need?
  4. How does React Gantt drag and drop work?
  5. How do progress and dependency arrows work?
  6. How do I save Gantt changes to a server?
  7. How does a project timeline in React work on a phone?
  8. Should I use a Gantt chart or a timeline?
  9. When is a paid Gantt library worth it?
  10. What are the common React Gantt chart pitfalls?
  11. How do I add it to my project?
  12. FAQ
    1. Is there a free React Gantt chart?
    2. How do I add drag and drop to a React Gantt chart?
    3. What dependency types does a Gantt chart use?
    4. What is the difference between a Gantt chart and a timeline?
    5. Is the Wingo UI Gantt free?

TL;DR

A usable React Gantt chart lets people drag bars to move tasks, drag their edges to change dates, set progress, and see dependency arrows that turn red when a task starts too early, on a desktop, on touch and from the keyboard. The Wingo UI Gantt does this from a tasks array and one onTaskChange callback, and turns into a task list with mini bars on a phone. If you need auto-scheduling, critical path, resource histograms or MS Project import, a paid Gantt library such as SVAR PRO, DHTMLX PRO or Bryntum is worth its price.

Published Oct 19, 2026

You need a React Gantt chart for a project plan, a roadmap or a client rollout. Drawing bars on a date axis takes an afternoon. Then people want to drag a bar to move a task, stretch it to change the end date, see which tasks wait on which, and open the plan on a phone, where a twelve week axis is 390px wide. This guide covers what a Gantt component has to handle, the free and paid options, the props that matter in the Wingo UI Gantt, saving changes to a server, and the point where a paid Gantt library is the better buy.

What should a React Gantt chart component handle?

Seven things:

  1. Bars you drag and resize. The body moves a task, the edges change its start or end, and the result snaps to whole days.
  2. Progress. A filled part of the bar, editable by drag or from a form.
  3. Dependency arrows from a predecessor's end to its successor's start, with a clear signal when the plan breaks one.
  4. Groups and milestones. Phases that fold, with a span and progress computed from their tasks, and diamonds for dates such as a go-live.
  5. Zoom. Days for the next two weeks, weeks for a quarter, months for a year.
  6. Keyboard and screen reader support. Every move possible without a mouse, and announced.
  7. A phone layout. A horizontal axis does not fit a phone, so the chart needs a different shape there.

Is there a free React Gantt chart?

Yes. If you search for a react gantt chart free of license fees, these are the options you will find. They differ in license, maintenance and how much you build yourself. Facts are from each project's docs, GitHub and npm, as of October 2026.

OptionLicense and priceReact supportWhat the free part covers
SVAR React Gantt (opens in a new tab)MIT core; PRO edition paid (30-day trial)@svar-ui/react-gantt 2.8.1, React 18 and 19Drag and drop, hierarchical tasks, dependencies, zoom, sorting, filtering, virtualization
DHTMLX Gantt (opens in a new tab)MIT Community Edition (dhtmlx-gantt 10.0.3); PRO from $799 (opens in a new tab) (Individual, one developer, one project)The free edition is plain JavaScript you wrap yourself; the official React wrapper @dhx/react-gantt is commercialCore chart, dependencies, drag and drop scheduling
Kibo UI Gantt (opens in a new tab)MIT source, npx kibo-ui add gantt (a shadcn registry item)Source component built on dnd kitDrag and resize, markers, today marker, grouped features
gantt-task-react (opens in a new tab)MIT0.3.9 from July 2022, peer React ^18Drag, progress, dependencies, view modes; the repository is archived
Bryntum Gantt (opens in a new tab)Commercial, from $940 per developer (small team rate, 3 or more licenses)React wrapperNo free edition
Wingo UI GanttPro source componentReact 19 source, npx wingo-ui@latest add ganttNot free; covered below

SVAR is the strongest free choice if you want a configured widget with a task grid, sorting and filtering out of the box. Kibo UI fits if you want source code in the shadcn style and plan to add dependencies and progress yourself, since its docs do not mention either. Skip gantt-task-react for new work: an archived repository gets no fixes.

What props does the Wingo UI Gantt need?

One array and one callback. tasks lists the rows, and onTaskChange receives every move, resize, progress drag and details save as { start, end, progress? }.

bash
npx wingo-ui@latest add gantt
tsx
"use client";
import { useState } from "react";
import { Gantt, type GanttTask } from "@/components/ui/gantt";
const PLAN: GanttTask[] = [
{ id: "design", name: "Design", start: new Date(2026, 9, 19), end: new Date(2026, 9, 30) },
{
id: "wireframes",
name: "Wireframes",
parentId: "design",
start: new Date(2026, 9, 19),
end: new Date(2026, 9, 23),
progress: 1,
assignee: { name: "Emma Carter" },
},
{
id: "visuals",
name: "Visual design",
parentId: "design",
start: new Date(2026, 9, 26),
end: new Date(2026, 9, 30),
progress: 0.3,
dependencies: ["wireframes"],
},
{
id: "build",
name: "Build pages",
start: new Date(2026, 10, 2),
end: new Date(2026, 10, 13),
assignee: { name: "Liam Walker" },
dependencies: ["visuals"],
},
{ id: "launch", name: "Launch", start: new Date(2026, 10, 16), end: new Date(2026, 10, 16), milestone: true, dependencies: ["build"] },
];
export function WebsitePlan() {
const [tasks, setTasks] = useState(PLAN);
return (
<Gantt
title="Website relaunch"
tasks={tasks}
locale="en-US"
onTaskChange={(task, change) =>
setTasks((list) => list.map((t) => (t.id === task.id ? { ...t, ...change } : t)))
}
/>
);
}

Three details in the task shape matter. end is inclusive, so a one day task has the same start and end. progress runs from 0 to 1. A task that other tasks name as parentId becomes a group: its span and its duration-weighted progress are computed from its children, and the chevron in the list folds it.

The props you will reach for next are defaultZoom (day, week or month, 40, 20 and 6 pixels per day), snap (day or week), listColumns (assignee, start, end, duration, progress, status), maxHeight (520px by default, with sticky headers and a sticky task list), editable and tone.

Drag a bar, stretch one of its edges, then open the zoom control and switch to months.

Drag "Client data import" to a new week and watch the pill above it show the new dates, then stretch a bar's right edge. Click any bar for its details, or tab into the chart and press Alt with the arrow keys to move the focused task
$ npx wingo-ui@latest add gantt
ProGantt docs

How does React Gantt drag and drop work?

A bar is three drag targets. The body moves the task and keeps its length, and the left and right edges move one end. While you drag, the original stays behind faded and a pill shows the new dates; on release the bar snaps to the snap unit. Near the edge of the timeline the view scrolls along, so you can drag a task into next month without letting go.

That is react gantt drag and drop with a mouse. On touch, a swipe across the chart must still scroll it. A bar on a touch screen lifts only after a press and hold (450ms, the library's long press default), so a quick swipe pans the timeline and a deliberate hold picks up the task. The same split between scrolling and dragging is explained in the dnd kit mobile touch drag tutorial.

The keyboard gets the same powers. Tab lands on one task, Up and Down move between tasks, Enter opens its details, Alt with Left or Right moves it by one snap step, Alt with Shift and Left or Right changes its end, and Escape cancels a drag. A live region announces each change, such as the task's new date range.

How do progress and dependency arrows work?

Set progressEditable and a small handle appears under each bar; drag it and progress moves in steps of 5%. The same value is editable in the details popover, together with the dates.

Dependencies are finish to start: list a predecessor's id in dependencies and an arrow runs from the end of that bar to the start of this one. When a task starts on or before its predecessor's last day, the arrow turns dashed red, the task list shows a warning icon, and the announcement names both tasks. The same check is exported as findDependencyViolations(tasks), so you can block a save or show a banner from the same rule the chart draws.

Switch on progress editing: drag the dot under a bar to set its progress, then drag "Client data import" before Specifications ends and watch its arrow turn dashed red
$ npx wingo-ui@latest add gantt
ProGantt docs

The chart does not move dependent tasks when you move a predecessor. That is a deliberate limit: the chart reports and your code decides. A simple forward pass on top of topoSortTasks, which orders predecessors first, pushes every late successor right:

ts
import { addDays, differenceInCalendarDays } from "date-fns";
import { topoSortTasks, type GanttTask } from "@/components/ui/gantt";
// pushes each task right until it starts the day after its latest predecessor ends (leaf tasks only)
export function pushDependents(tasks: GanttTask[]): GanttTask[] {
const byId = new Map(tasks.map((t) => [t.id, t]));
for (const { id } of topoSortTasks(tasks)) {
const task = byId.get(id)!;
let earliest: Date | null = null;
for (const depId of task.dependencies ?? []) {
const predecessor = byId.get(depId);
if (!predecessor) continue;
const next = addDays(predecessor.end, 1);
if (!earliest || next > earliest) earliest = next;
}
if (earliest && task.start < earliest) {
const days = differenceInCalendarDays(earliest, task.start);
byId.set(id, { ...task, start: addDays(task.start, days), end: addDays(task.end, days) });
}
}
return tasks.map((t) => byId.get(t.id)!);
}

Call it inside onTaskChange after you apply the change:

tsx
onTaskChange={(task, change) =>
setTasks((list) => pushDependents(list.map((t) => (t.id === task.id ? { ...t, ...change } : t))))
}

It only pushes tasks later. Moving a predecessor earlier leaves its successors where they are, so closing a gap stays a decision someone makes by dragging.

How do I save Gantt changes to a server?

Return a promise from onTaskChange. The bar keeps its new place while the request runs, and if the promise rejects it springs back to where it was and the chart announces that the change failed. Returning false cancels a change on the spot, which is how you refuse a move by rule.

tsx
"use client";
import { useState } from "react";
import { format } from "date-fns";
import { Gantt, type GanttTask } from "@/components/ui/gantt";
const day = (date: Date) => format(date, "yyyy-MM-dd");
export function SavedPlan({ initial }: { initial: GanttTask[] }) {
const [tasks, setTasks] = useState(initial);
return (
<Gantt
title="Website relaunch"
tasks={tasks}
locale="en-US"
progressEditable
onTaskChange={async (task, change) => {
const response = await fetch(`/api/tasks/${task.id}`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ start: day(change.start), end: day(change.end), progress: change.progress }),
});
if (!response.ok) throw new Error("Not saved");
setTasks((list) => list.map((t) => (t.id === task.id ? { ...t, ...change } : t)));
}}
/>
);
}

Send dates as calendar days, as above. A Date serialized with toISOString() is in UTC, so a task that ends at local midnight in Berlin arrives on the server as 10 or 11 PM the day before (depending on daylight saving time). If the server keeps only the date part, the bar moves a day earlier after a reload.

How does a project timeline in React work on a phone?

It stops being a timeline. Below 512px of its own width the Gantt becomes a list of tasks grouped by phase, each with a mini bar placed inside the project's span, so you can still see what runs when. Tap a task and its details open in a bottom sheet below 768px (turn that off with responsive={false}). Between 512 and 1023px the list keeps only the names, and the extra columns appear from 1024px.

The switch follows the chart's own width, so a Gantt in a narrow side panel on a desktop gets the list too.

Should I use a Gantt chart or a timeline?

Use the Gantt for the plan and the Timeline for the history. A Gantt chart is bars with a start and an end: durations, overlaps and dependencies. A timeline is events at a point in time: "Specifications approved", "Invoice paid", "Shipped". A search for a react gantt timeline or a project timeline React component can mean either, so decide by the data: rows with a start and an end need the Gantt, single moments need the Timeline.

If the rows are rooms, cars or people and the bars are bookings, neither fits: that is a resource scheduler, covered in the React resource scheduler guide with the Scheduler component.

When is a paid Gantt library worth it?

When the chart has to do project management, not only show it. The Wingo UI Gantt draws finish-to-start dependencies, checks them, and leaves rescheduling to your code. It has no critical path, no resource histograms, no working-time calendars (weekends are shaded, holidays are not modeled), no baselines and no export. It virtualizes the rows once more than 150 are visible, but it does not load tasks on demand from a backend.

The paid editions exist for exactly that list. As of October 2026, SVAR PRO (opens in a new tab) adds auto-scheduling across all four dependency types, critical path, constraints, resource planning, working-time calendars, baselines, export to PDF, PNG, Excel and MS Project, and MS Project import. DHTMLX PRO (opens in a new tab) adds auto-scheduling, critical path, resource management, baselines, project and resource calendars and the official React wrapper, from $799 for one developer and one project. Bryntum (opens in a new tab) starts at $940 per developer at its small team rate (3 or more licenses). If your users are project managers who import MS Project files and ask what slips when a task slips, buying one is cheaper than writing a scheduler.

For a plan inside a product (a client rollout in a CRM, a roadmap in an admin), you need the seven things from the first section, your design tokens and code you can change. That is what the Gantt is built for. Wingo UI Pro is $8 a month, $80 a year or $150 once, as of October 2026 (pricing).

What are the common React Gantt chart pitfalls?

  • Exclusive end dates. Store end as the last day of the task, inclusive. Mixing inclusive and exclusive ends makes every bar one day too long or too short.
  • Group dates from the database. A group's span comes from its children. Do not save a separately edited group span and expect it to win.
  • Cycles. A depends on B and B on A. The chart warns in development and topoSortTasks keeps such tasks in their original order, but a forward pass like pushDependents will not resolve them.

How do I add it to my project?

Run npx wingo-ui@latest add gantt. The CLI copies the source into components/ui, adds the components and hooks it builds on (among them Popover, Date Picker, Slider, Progress, Tooltip and the long press hook), and installs date-fns, @tanstack/react-virtual, motion and lucide-react. For boards instead of plans, see the React kanban board guide. More single-component deep dives are in the component guides category, and the React form components guide applies the same touch, keyboard and screen reader rules to every form control.

Components in this post

  • Gantt

    A React Gantt chart: project tasks as bars you drag and resize, with progress, dependency arrows, milestones, groups and a phone task list.

    Pro
  • Timeline

    A React timeline component for activity feeds, audit trails, changelogs and order tracking, with icons, relative times and day groups.

    Pro

FAQ

Is there a free React Gantt chart?

Yes. SVAR React Gantt has an MIT-licensed core with drag and drop, dependencies and zoom, DHTMLX Gantt has an MIT Community Edition you wrap in React yourself, and Kibo UI ships an MIT Gantt as source through its shadcn-style registry. gantt-task-react is MIT too, but its GitHub repository is archived and its last npm release is from July 2022.

How do I add drag and drop to a React Gantt chart?

Treat a bar as three drag targets: the body moves the task, the left edge changes the start and the right edge changes the end, and snap the result to whole days on release. The Wingo UI Gantt does this for you and reports every change through onTaskChange with the new start, end and progress.

What dependency types does a Gantt chart use?

Project tools know four: finish to start, start to start, finish to finish and start to finish. Finish to start is by far the most common, and it is the only type the Wingo UI Gantt draws; SVAR PRO auto-schedules across all four.

What is the difference between a Gantt chart and a timeline?

A Gantt chart plans work as bars on a time axis, so you see durations, overlaps and dependencies. A timeline lists events that happened at a point in time, such as an activity feed or an order history, which is what the Wingo UI Timeline component is for.

Is the Wingo UI Gantt free?

No. The Gantt and the Timeline are Pro components. The Popover, Tooltip and Progress the Gantt builds on are free.

  • Gantt chart
  • Drag and drop
  • Project planning
  • Mobile UI
  • React

Share

SR

About the author

Serban Rusu

Founder of Wingo UI

Serban Rusu founded Wingo UI. He builds its component library, CLI and MCP server, and writes about React interfaces for phones and AI coding agents.

More from Serban
Keep reading

Related posts

All posts
Component guides

Embla Carousel React: Accessible Slides, No Layout Shift

Build an embla carousel react component for photos, listings, testimonials and onboarding, with keyboard controls, pausable autoplay and no layout shift.

SRSerban Rusu·Oct 19, 2026·9 min read
Component guides

React Animated Number Counter: Rolling Odometer Digits

Build a React animated number counter that rolls each digit like an odometer, takes its separators from Intl, holds its width and respects reduced motion.

SRSerban Rusu·Oct 19, 2026·9 min read
Component guides

React Audio Player with Waveform: Scrub, Seek, Peaks

Build a React audio player with waveform scrubbing for podcasts, chat voice notes and call logs, with keyboard seek, precomputed peaks and no layout shift.

SRSerban Rusu·Oct 19, 2026·9 min read
Newsletter

Get new posts by email

New guides, tutorials and comparisons from the Wingo UI blog, sent when they are published.

No spam. Unsubscribe at any time.

WingoUI

Animated, configurable, mobile-first React components and blocks. Copy the source, make it yours, and let your coding agent build with it.

Product

  • Components
  • Templates
  • Pricing
  • AI agents
  • Theme generator

Resources

  • Docs
  • Blog
  • Changelog
  • Changelog RSS
  • llms.txt

Legal

  • Terms
  • Privacy
  • Refunds
  • License
  • Imprint

Component categories

  • Buttons & Actions
  • Inputs
  • Forms
  • Navigation
  • Overlays
  • Feedback
  • Data Display
  • Tables & Lists
  • Charts & Stats
  • Layout
  • Media
  • AI Kit
  • Text & Effects
  • Mobile
  • Commerce
  • Marketing Sections
  • Blocks
  • Hooks & Utilities

© 2026 Wingo UI

Wingo UI