mantine-gantt
A gantt chart component for mantine
Installation
Usage
Custom columns & click-to-open modal
Pass columns to customize the left panel (the default columns are Task Name, Start,
End and Duration). Use onTaskClick to react to clicks - here it opens a modal with
task details.
Grouping tasks
Set parentId on a task and it becomes a child row. A task that has children renders as a
summary bar: it spans its whole subtree and shows a duration-weighted average progress, so the
dates you give a parent are only a placeholder. Nesting goes as deep as you need. Rows are
collapsible via the chevron - defaultExpandedIds picks which parents start open (omit it and
everything is open), and onToggleExpand reports each toggle.
View modes
viewMode switches the timeline scale between day (default), week and month. It shrinks
the day column derived from columnWidth rather than changing the underlying day grid, so drags
still snap to whole days. weekStart controls the header's week numbering and the grid separators.
locale (default 'en') sets the language of month names and dates - pass 'de', or
navigator.language to follow the browser.
Navigation, zoom and selection
scrollTo-'today', aDate, or{ taskId }scrolls the timeline there on mount and whenever the value changes (a task also brings its row into view).- Ctrl+wheel over the timeline zooms the day column between 8px and 200px around the cursor;
onColumnWidthChangereports the new width. Holding the middle mouse button autoscrolls the timeline in the direction you move, on every platform. isNonWorkingDayreplaces the default Saturday/Sunday shading with your own predicate (holidays, company calendar). It only affects the shading - durations stay in calendar days.selectedTaskIdmarks a task's bar and list row withdata-selected; pair it withonTaskClickto build a selection.- While dragging, the bar shows its snapped start/end above the cursor (
showDragLabel={false}turns it off); Escape cancels the drag.
Column width: 40px (Ctrl+wheel to zoom, middle button to autoscroll)
Phones and narrow containers
- The button in the task list header collapses the panel to a narrow strip, giving the timeline
the full width (task names stay readable on the bars). While the chart is narrower than the
task list plus 240px - a phone in portrait - the panel starts collapsed and follows the
container width until the user toggles it.
defaultTaskListCollapsed={false}opts out;taskListCollapsed+onTaskListCollapsedChangemake it controlled. - On touch screens a swipe always pans the timeline, even when it starts on a bar. To move, resize or link a task, press and hold the bar (or a handle) for 300ms, then drag.
Critical path & baselines
highlightCriticalPath runs CPM over the dependency graph and paints the zero-slack tasks and
links with criticalPathColor. Independently, any task with a baseline gets a thin planned bar
underneath the actual one - turn those off with showBaselines={false}.
Milestones
Set type: 'milestone' on a task to render it as a diamond instead of a bar. A milestone is a
zero-length marker pinned to its start day - it can be dragged and linked like any task, but it
cannot be resized and its duration is ignored for rendering. Milestones participate in the
critical path calculation and in auto-scheduling like regular tasks.
Auto-scheduling
With autoSchedule, moving or resizing a task pushes every finish-to-start successor so it never
starts before its predecessors end. The cascade is transitive (a whole chain shifts together) and
picks the latest predecessor when a task has several dependencies. It works with drags, resizes
and keyboard nudges alike. Turned off by default.
Dependency types and lag
An entry in dependencies is either a task id or an object. The id is shorthand for a
finish-to-start link with no lag, so existing data keeps working.
type is 'FS' (default), 'SS', 'FF' or 'SF' - predecessor first, S for start and F
for finish. lag is whole days, negative for a lead. The arrow attaches to the ends the type
names, autoSchedule enforces the constraint and the critical path accounts for it.
Dragging the link connector always creates a finish-to-start link; set other types and lags in
your data. Code that reads dependencies can normalize both shapes with normalizeDependency:
Working days
By default duration counts calendar days and isNonWorkingDay only shades columns. With
workingDays, duration, baseline.duration and dependency lag count working days: a 5-day
task that starts on Friday ends the next Thursday and its bar stretches across the weekend.
- A task dropped on a non-working day snaps to the next working day in the direction it moved.
- Resizing recounts the working days between the bar's new ends.
autoScheduleplaces successors on working days.isNonWorkingDaydefines the calendar, so holidays work the same way as weekends.
A custom column gets the computed row as a third argument; row.span is the number of calendar
days the bar covers, which is what you need to print an end date:
Deleting dependency links
Click a dependency arrow to delete that link. The component removes the source id from the
target's dependencies and fires onLinkDelete(fromTaskId, toTaskId, type) alongside onTasksChange,
mirroring how link creation works.
Markers
markers draws extra vertical lines next to the today marker: a deadline, a release, a sprint
end. Each takes a date (YYYY-MM-DD), an optional label and a color (default orange).
A marker outside the timeline is not rendered and does not widen it - set startDate / endDate
if it has to be visible.
Read-only and locked tasks
readOnly turns off every edit: drag, resize, linking, link deletion and keyboard nudges.
onTaskClick, selection, expand/collapse, scrolling and zoom keep working. To freeze a single
task, set locked: true on it. A locked task can still be the target of a new link, and
autoSchedule still shifts it, because a successor that starts before its predecessor ends would
make the chart lie.
To reject or clamp a single change instead, use controlled mode and decide in onTasksChange:
Controlled and uncontrolled
Pass defaultTasks and the component owns the task list (uncontrolled) - this is what the demos
above do. Pass tasks together with onTasksChange and your own state is the single source of
truth (controlled): the component keeps no copy, so a dragged bar only moves once the new tasks
prop arrives. Use this mode to drive the chart from a query cache, a store, or an undo/redo stack.
onTaskUpdate, onLinkCreate and onLinkDelete keep working in both modes - they fire
alongside onTasksChange, not instead of it.
Migrating from 0.2.x: <Gantt tasks={x} /> becomes <Gantt defaultTasks={x} />.