Gantt Plugin Roadmap
June 13, 2026 · View on GitHub
Status: Planned. Gap analysis done (June 2026) against SVAR React Gantt. Current
@object-ui/plugin-ganttis a draggable day-scale bar chart; it lacks the project-management semantics (dependencies, hierarchy, milestones, real time scales) that define a Gantt chart. SVAR core is GPLv3 — feature reference only, no code reuse (we are MIT).Tracked from the main ROADMAP.md § P2.11.
What we already have
Bar drag/resize with day snapping + optimistic persistence, pinch-to-zoom, responsive/mobile pass, Today marker + jump-to-today, weekend highlighting, semantic color fallback, i18n, inline edit (double-click), record detail drawer on click, delete confirmation.
Phase 1 — Dependency Links Rendering (highest ROI) ✅
- Render dependency arrows as an SVG overlay in
GanttView(orthogonal elbow routing, arrowhead markers, backward-link detour) - Support the 4 link types: finish-to-start (default), start-to-start, finish-to-finish, start-to-finish — per-dependency
{ id, type }object form;normalizeDependenciesaccepts CSV strings, id arrays, object arrays with id/type aliases - Recompute arrow paths live during bar drag/resize preview
- Highlight a task's links on hover (and while dragging)
- Tests: link parsing (string id, array,
{id, type}object), path anchors per type, hover highlight, drag re-render, backward links (8 new GanttView tests + 6 normalizeDependencies tests)
Phase 2 — Real Time Scales (resurrect viewMode) ✅
- Implement day/week/month/quarter column generation in
timeColumns— calendar-true column widths over one linear ms→px mapping (pxPerDay = columnWidth / nominalDays), so bars, grid, links and the Today marker stay aligned in every mode - Two-row scale header: month groups over day/week units, year groups over month/quarter units
- Restore the view-mode segmented control in the toolbar; zoom buttons fall through to the next coarser/finer granularity at min/max column width
- Drag snapping respects active granularity (day/week columns, calendar-clamped month/quarter shifts preserving duration on move)
- Tests: column generation per mode, header groups/labels, bar geometry per granularity, week + month snap behavior (8 new tests)
Phase 3 — Task Hierarchy & Types ✅
-
parentField(+task.parent) → task tree, depth-indented rows, expand/collapse chevrons in the task list; orphans and parent cycles surface as roots instead of dropping rows - Summary (parent) bars: bracket-style slim bar with end caps spanning the children rollup range; read-only (children drive it)
- Milestone type: diamond marker via
typeField/task.typeor theend <= startheuristic; movable, not resizable; links anchor at the diamond center - Auto-rollup: summary dates = min/max of descendants, progress = duration-weighted child progress (client-side, display via
data-progress) - Tests: tree building, orphan + cycle handling, collapse hides rows/links, summary range/progress math, milestone rendering + link anchors (9 new tests)
Phase 4 — Interaction Polish ✅
- Progress drag handle on the bar — grip at the progress boundary, 1% snapping, live fill preview, commits
onTaskUpdate({progress}) - Rich hover tooltip (title, dates, duration, progress) on task bars, milestones and summary brackets
- Context menu on bar/row — View details / Edit inline / Delete; closes on outside click or Escape (add-dependency is covered by drag-to-create)
- Keyboard support: focusable gantt body, ArrowUp/Down row navigation, Enter to open, Delete to delete, ArrowLeft/Right collapse/expand;
tree/treeitemroles with aria-level/-selected/-expanded - Drag-to-create dependency — connector dot on bar edge, dashed rubber band, drop-target highlight; fires
onDependencyCreate(source, target, 'fs'),ObjectGanttappends to the dependencies field preserving its shape (CSV ↔ array) - Row drag-to-reorder — HTML5 drag in the task list, sibling-scoped, fires
onTaskReorder(task, before)for the host to persist (sort-field wiring is host-specific) - Tests: progress drag + clamping, tooltip, context menu routing/Escape, keyboard nav + collapse, link create + empty-space release, reorder + cross-parent guard (11 new tests)
Phase 5 — Scale & Performance ✅
- Virtualized row rendering (windowing) for both task list and timeline — spacer-div windowing over flattened rows (≈viewport + 6-row overscan rendered), driven by scroll position + ResizeObserver-measured viewport; dependency-link SVG keeps absolute row coordinates and skips links fully outside the window
- Virtualized timeline columns for multi-year ranges — prefix-sum column offsets + binary-free linear
visibleRangescan; header groups, header units and the background grid render as absolutely-positioned cells inside the ±240px overscan window - Fullscreen mode toggle — toolbar button drives the native Fullscreen API on the Gantt container, icon/aria reflect
fullscreenchange - Custom vertical markers —
markersprop ({date, label?, color?}), rendered like the Today line on the shared ms→px mapping; out-of-range/invalid dates dropped; passed throughObjectGanttviaschema.markers - Tests: 1000-row windowing + spacer heights, scroll window shift, windowed link anchoring, multi-year column windowing, fullscreen enter/exit, marker mapping/fallback color (8 new tests)
Phase 6 — Advanced (SVAR PRO territory, differentiators)
- Critical path computation + slack visualization — CPM forward/backward passes in
scheduling.ts(zero-slack chain), toolbar toggle (Activity icon) highlights critical bars/milestones/summaries + joining link arrows in red;criticalPathDefaultprop /schema.criticalPathstart it on - Baselines (planned vs actual bars) —
baselineStart/baselineEndper task render a thin reference strip hugging each row's bottom (summary / task / milestone) on the shared ms→px mapping;showBaselinesprop /schema.showBaselines, mapped inObjectGanttviabaselineStartField/baselineEndField - Auto-scheduling: dependency-driven date shifting (forward, finish-to-start first) —
computeProjectReschedule(顺延: push successors later, durations preserved, never earlier; honors fs/ss/ff/sf; summaries fixed), toolbar button (Wand2) does a one-shot whole-project reschedule viaonTaskUpdate;autoScheduleprop, auto-on inObjectGanttwhendependenciesFieldset - Working calendar (skip weekends/holidays in duration math) —
WorkingCalendar(skipWeekends,holidaysISO-day Set) measures durations in working days;computeCriticalPath/computeProjectReschedulesnap rescheduled tasks to working-day boundaries (fs/ss bump vianextWorkingDay, ff/sf back-derive viasubWorkingDays);workingCalendarprop, derived inObjectGanttfromschema.skipWeekends/schema.holidays - Undo/redo for drag/edit operations —
commitTaskUpdatesrecords before/after field deltas per mutation (group-drag / auto-schedule batched into one entry) and replays throughonTaskUpdateagainsttasksRef; toolbar Undo/Redo buttons + Ctrl/Cmd+Z, Ctrl/Cmd+Shift+Z, Ctrl/Cmd+Y; only shown whenonTaskUpdateis wired - Export PNG (client-side) — toolbar button (Download) rebuilds the whole chart (virtualization-independent) as a standalone SVG with concrete hex colors, rasterizes to a 2× PNG via canvas, downloads
gantt-<mode>.png; zero dependencies. (PDF / MS Project XML still pending.)