ComponentsCalendar & time

Gantt

A task plan on a time axis. The task list is a WAI-ARIA treegrid that holds everything: WBS number, dates, duration, progress and predecessors, all editable inline. Beside it are bars, summary brackets, milestones, finish-to-start links, a today marker and non-working days. Drag a bar to move it, pull its end to resize, or drag its handle onto another bar to link them. Successors are auto-scheduled on working days.

Own engine: useTimeScale, usePointerDrag, @tanstack/react-virtual scheduler/gantt.tsx, scheduler/core/gantt.ts, scheduler/core/time-scale.ts, sortable/use-time-scale.ts, styles/calendar.csstheme · material · accent · density · font
Task
Owner
Start
End
Duration
Progress
Website relaunch · Lumen Spa
Oct 26
Dec 9
33 working days
37%
Discovery
Oct 26
Nov 4
8 working days
100%
Stakeholder interviews
Oct 26
Oct 30
5 working days
100%
Content audit
Nov 2
Nov 4
3 working days
100%
Design
Nov 5
Nov 20
12 working days
36%
Wireframes
Nov 5
Nov 11
5 working days
70%
Visual design
Nov 12
Nov 20
7 working days
10%
Build
Nov 23
Dec 9
13 working days
0%
Booking flow
Nov 23
Dec 4
10 working days
0%
CMS integration
Nov 30
Dec 9
8 working days
0%
Launch
Unassigned
Dec 11
Dec 11
Milestone
–

Installation

$ pnpm add @vamos-ui/react

The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";

Usage

import { Gantt } from "@vamos-ui/react/scheduler";
import { trWorkCalendar } from "@vamos-ui/react/locale-data";

<Gantt
  tasks={tasks}            // { id, parentId?, title, start, end (YYYY-MM-DD, inclusive), progress?, type? }
  links={links}            // { id, from, to, type: "FS", lagDays? }
  defaultScale="week"
  workCalendar={trWorkCalendar}
  onTaskChange={(batch) => api.tasks.updateMany(batch)}   // the task + every pushed successor
  onLinkCreate={(l) => api.links.create(l)}
/>

// Scheduling without React (server, worker)
import { scheduleForward, detectCycles } from "@vamos-ui/react/scheduler";

The treegrid is the accessible source of truth, and the timeline is aria-hidden. Use ↑/↓ for rows, ←/→ for cells (on the first cell, ← and → collapse and expand), Home and End, and Enter or F2 to edit a cell. Enter saves and Escape cancels. Date edits are the non-drag path (WCAG 2.5.7).

Bars are opaque colour mixes with no blur. The timeline sits on one surface.

The first release has finish-to-start links only. Critical path, baselines and RTL timeline mirroring come later.

Examples

Dependencies and auto-scheduling

A partner launch plan on trWorkCalendar. Move a task and its finish-to-start successors move with it, on working days only (29 October is skipped). Edit the Predecessors cell (“1.2, 3”) to add or remove links. A link that would create a loop is refused.

Task
Start
End
Duration
Predecessors
Partner contract signed
Oct 23
Oct 23
Milestone
–
Onboarding workshop
Oct 26
Oct 28
3 working days
1
Co-branded landing page
Oct 29
Nov 6
6 working days
2
Sales enablement
Nov 9
Nov 13
5 working days
3
Joint launch
Nov 16
Nov 16
Milestone
4

Zoom levels

A hiring timeline at day, week, month and quarter zoom. Week numbers follow the locale's rules (W46). Overdue tasks (unfinished and past today) get a red edge.

Task
Start
End
Hiring plan approved
Jan 15
Jan 15
Recruiting · engineering, overdue
Feb 2
May 29
Recruiting · sales, overdue
Mar 2
Jul 31
Onboarding cohort 1
Jun 1
Jun 26
Onboarding cohort 2, overdue
Sep 7
Oct 2
Year-end reviews
Nov 16
Dec 18

Client portal (read-only)

readOnly and scales={[]}: a calm progress view for clients, with no handles and no editing.

Task
End
Progress
Brand strategy
Oct 16
100%
Logo & identity
Nov 6
100%
Packaging design
Nov 20
55%
Print proofs
Nov 27
0%
Hand-over
Nov 30
–

2,000 rows

400 work packages × 5 phases. Rows are virtualized from 150 (virtualizeAt), in the task list and the timeline together.

Task
Start
End
Duration
Progress

API

Gantt

PropTypeDefault
tasks
{ id, parentId?, title, start, end, progress? (0–1), type?: "task" | "milestone" | "summary", assignees?, tone?, editable? }. Parents span their children automatically.
GanttTask[]—
links
{ id, from, to, type?: "FS", lagDays? }. This release draws and schedules finish-to-start links.
GanttLink[]—
scale / defaultScale / onScaleChange
Zoom level.
"day" | "week" | "month" | "quarter""week"
scales
Zoom options in the toolbar. [] hides the switch.
GanttScale[]all four
workCalendar
Working days for durations, scheduling and the shaded non-working days (day zoom).
WorkCalendarfrom locale
durationUnit
How durations are counted and shown (“6 working days”).
"workdays" | "days""workdays"
onTaskChange
One batch per edit, including successors that moved. Applied at once; reject to revert.
(changes: { id, start, end, progress? }[]) => void | Promise<void>—
onLinkCreate / onLinkDelete
From dragging the connect handle onto another bar, clicking a link, or the Predecessors cell. Delete offers Undo.
(link) => void | Promise / (id) => void | Promise—
autoSchedule
Push successors later when a task moves (never pulls them earlier).
booleantrue
readOnly
No drag, no inline editing.
booleanfalse
columns
Task-list columns: title, assignees, start, end, duration, progress, predecessors.
GanttColumnKey[]["title", "start", "end", "duration", "progress"]
gridWidth / defaultGridWidth / onGridWidthChange
Task-list width. Drag the splitter, or focus it and use ←/→.
number (px)—
collapsed / defaultCollapsed / onCollapsedChange
Ids of collapsed parent rows.
string[]—
height / rowHeight / virtualizeAt
Scroll height, row height (follows density by default), and the row count from which rows are virtualized.
string | number / number / number"32rem" / density / 150
today
Sets the today marker and the overdue state.
string (YYYY-MM-DD)today in the locale zone
toolbar
Extra toolbar content.
ReactNode—
labels
Overrides for the gantt namespace strings.
Partial<GanttLabels>—

core (React-free)

PropTypeDefault
scheduleForward(tasks, links, cal?, unit?)
Pushes FS successors after their predecessors, working-day aware. Unchanged tasks keep their identity.
GanttTask[]—
detectCycles(links) / createsCycle(links, from, to)
Dependency loop checks.
string[][] / boolean—
rollupSummaries / flattenTasks / visibleTasks
Parent spans and progress, WBS numbering, collapsed views.
functions—
taskDuration / moveTaskTo / linkViolations
Working-day durations, moves that keep length, FS links that are violated.
functions—