Skip to content
WANCRAFT

G.178Data & Feedback

Gantt Chart

A project timeline with draggable, resizable bars, dependency arrows, milestones, progress and day / week / month zoom.

NewReactSVGTailwindadvanced

Overview

Gantt Chart lays tasks out on a calendar: each row has a bar from its start to its end date, filled by its progress, and milestones are diamonds. Finish-to-start dependencies are drawn as routed connector arrows that turn red and dashed when a task starts before its predecessor ends. Drag a bar to move it or drag either edge to resize it, snapping to whole days; with the keyboard, arrows move the focused bar by a day, Shift + arrows change its end and Shift + Alt + arrows its start, and every bar has a full description such as "Design, 8 Oct to 17 Oct, 60% complete, after Research". Zoom between day, week and month scales (the view stays centred on the same date), scroll sideways with a sticky task column, and see today marked with a line. Dates are whole UTC days, so the chart renders identically on the server and in every time zone; pass today or let it appear after hydration.

01Installation

Method 01 · Registry

CLI verified

Uses the shadcn CLI in a project initialised with shadcn init. Installs the file to components/ui/gantt-chart.tsx and adds its dependencies.

npx shadcn@latest add https://wancraft.my/r/gantt-chart.json

Method 02 · Copy and paste

  1. 1. No extra dependencies — React and Tailwind CSS only.
  2. 2. Copy the source from the Code tab into components/ui/gantt-chart.tsx.
  3. 3. Import it and adjust props.
Dependencies
None
Peer
react ≥ 18, tailwindcss ≥ 4
Added
13 Oct 2026
Updated
—

02Usage

The default configuration. Change properties above to generate a tailored example in the Usage tab.

example.tsx
import { GanttChart, type GanttTask } from "@/components/ui/gantt-chart";
import { useState } from "react";

export function GanttChartExample() {
  const [tasks, setTasks] = useState<GanttTask[]>([
    { id: "research", name: "Research", start: "2026-10-01", end: "2026-10-07", progress: 100 },
    { id: "design", name: "Design", start: "2026-10-08", end: "2026-10-17", progress: 60, dependencies: ["research"] },
    { id: "launch", name: "Launch", start: "2026-10-23", end: "2026-10-23", milestone: true, dependencies: ["design"] },
  ]);

  return (
    <div className="w-full max-w-4xl">
      <GanttChart tasks={tasks} onChange={setTasks} today="2026-10-13" />
    </div>
  );
}

03Props

PropTypeDefaultDescription
tasksGanttTask[]—Required. { id, name, start, end, progress?, milestone?, dependencies? } with "YYYY-MM-DD" dates; end is inclusive.
onChange(tasks: GanttTask[], changed: GanttTask) => void—Called after a drag or keyboard edit. Without it the chart is read-only.
zoom / defaultZoom / onZoomChange"day" | "week" | "month"— / "week"Scale: 36, 12 or 4.5 px per day; controlled or uncontrolled.
todaystring—"YYYY-MM-DD" for the today marker; when omitted it is computed in the browser after hydration (SSR-safe).
showTodaybooleantrueToday line, label and the Today scroll button.
showDependenciesbooleantrueRouted finish-to-start arrows; conflicts are red and dashed.
showProgressbooleantrueProgress fill and percentage inside bars.
showWeekendsbooleantrueShade Saturdays and Sundays in day and week zoom.
rowHeightnumber40Row height in px; bars are about 56% of it.
labelWidthnumber168Width of the sticky task-name column in px.
readOnlybooleanfalseDisable drag and keyboard edits (bars stay focusable for reading).
accentstring"#FF7448"Bars, progress, milestones, today marker and focus rings.
labelstring"Project timeline"Accessible name of the chart group.

04Features

  • 01Bars positioned by start / end dates with progress fills; milestones drawn as diamonds
  • 02Drag to move and drag either edge to resize, snapping to whole days; state updates only when the snapped day changes
  • 03Routed dependency arrows with a red dashed style when a task starts before its predecessor ends
  • 04Day, week and month zoom that keeps the centred date, horizontal scroll and a sticky task column
  • 05Today marker that is SSR-safe: pass today, or it is computed after hydration
  • 06Keyboard: Up / Down between tasks, arrows move a day, Shift + arrows resize the end, Shift + Alt + arrows the start
input · draginput · keyboardinput · clickinput · pointer

05Accessibility

  • The chart is a labelled group; bars are a single tab stop (roving tabindex) with role="button", aria-roledescription "task bar" or "milestone" and keyboard instructions via aria-describedby.
  • Each bar's name gives its dates, progress, dependencies and conflicts, e.g. "Design, 8 Oct to 17 Oct, 60% complete, after Research".
  • Every move or resize is announced in a polite live region ("Design: 9 Oct to 18 Oct.").
  • The date scale, task column, grid and arrows are aria-hidden duplicates of what the bar names already say.
  • Zoom buttons use aria-pressed; the read-only mode keeps bars focusable and readable.
  • On touch, dragging a bar horizontally edits it while vertical swipes still scroll the page; there are no animations to reduce.

06Limitations

  • Dependencies are finish-to-start only, and moving a task does not reschedule its successors (conflicts are highlighted instead).
  • Month and weekday labels are English; all rows render (no virtualisation) and the plan cannot be reordered.