Lumeo

Gantt

A project timeline with draggable task bars, dependencies, milestones, hierarchy, and a real commit gate. Renders with a Razor-first engine — no third-party charting library.

Installation

dotnet add package Lumeo.Gantt

One-time app setup (AddLumeo(), CSS & JS) is covered in the installation guide.

Usage

@using Lumeo

<GanttChart />

When to Use

  • Planning a project with ordered phases, cross-task dependencies, and milestones.
  • Grouping work by swim-lane, or modeling real parent/child hierarchy with a tree pane.
  • Letting stakeholders see "what blocks what" at a glance, drag to reschedule, and drag the progress handle to mark completion.
  • Enforcing your own scheduling rules — reject an invalid drag, or silently snap it to a grid — via the OnTaskUpdate commit gate.

Four phases (ParentId hierarchy, tree pane on automatically), cross-phase Dependencies, and two IsMilestone diamonds — "Kickoff approved" and "Go-live". This is also Day mode's own upper header row: the "W32 Aug 3 – 9"-style bands are ISO-8601 week numbers, automatic in every Day-mode demo on this page.

OnTaskUpdate is a gate, not a notification: it can reject a drag (false), accept it as proposed (true), or accept it with an adjustment (GanttUpdateResult.AcceptWith(...)) that snaps the committed Start/End to different values. Try dragging a bar here — this demo rejects anything that would start before today, and snaps every other drop onto the nearest Monday.

Gate log (most recent first)
Drag a bar to see the gate's verdict here.

Drag the progress handle at the base of a bar to change completion. OnProgressChange fires the v2-parity notification; OnTaskUpdate (Source=Progress) gates the same edit like every other gesture.

Last progress change
Drag a progress handle to see it here.

Use the built-in toolbar to switch between 7 zoom levels — QuarterDay, HalfDay, Day, Week, Month, Quarter, and Year. ShowZoomControl renders the segmented switcher shown here.

Hold Ctrl/Cmd and scroll over the timeline to zoom — the date under your cursor stays under your cursor. A bare wheel keeps scrolling the page/pane like normal; at the finest (Day) or coarsest (Year) level, Ctrl/Cmd+wheel is left alone so the browser's own page-zoom takes over instead. WheelZoom="false" turns this off.

Tab into a bar, then use / (or /) to move focus between tasks. Hold Shift and press / to move the focused task by a day, or Shift+/ to grow/shrink its end date — both flow through the same OnTaskUpdate gate a mouse drag does, tagged GanttTaskUpdateSource.Keyboard.

Pass a GroupBy function and/or set GroupLabel on each GanttTask. Tasks are sorted by group and a section-header row is injected before the first task of each group.

Set GanttTask.ParentId to build real parent/child hierarchy. The tree pane shows the task-name column plus any extra GanttTreeColumns you supply (here, a typed "Progress" column) — drag the divider at the pane's trailing edge to resize it.

The gear icon in the toolbar opens GanttSettingsMenu — Display/Behavior/Region/Style groups covering row checkboxes, summary bars, off-screen indicators, infinite scroll, the now indicator, off-day shading, read-only, drag-create, row reorder, first day of week, off days, and per-group colouring. Off-screen indicators (chips at the scroll edges) appear once you scroll a task out of view — try Month/Year zoom on the wide roadmap above, or scroll this chart horizontally.

Set Readonly="true" to lock the chart — bars can't be dragged, resized, or created.

Use the BarColor delegate to return any CSS colour (hex, rgb, or a CSS variable like var(--color-destructive)) per task — or set ColorByGroup="true" (shown in the settings-menu demo above) for automatic per-group palette colouring.

NowIndicator draws a precise current-time line — only meaningful at sub-day granularity, so this demo starts in HalfDay zoom (12-hour columns); switch to Day/Week/etc. via the toolbar and it disappears, same as it would in your own app. MarkOffDays tints weekend columns using OffDays (or a region-appropriate default derived from the current culture) at any zoom level.

ShowRowCheckboxes renders a checkbox column in the tree pane. Only LEAF tasks are ever members of SelectedIds — checking a parent phase toggles every descendant, not the phase itself.

Nothing selected.

AllowRowReorder lets you drag rows in the tree pane to re-sequence a backlog. Reorder is scoped to siblings under the same parent (or the root level here, since these tasks have none) — OnRowReorder fires once per completed drop with the resolved before/after index.

Drag a row to reorder the backlog.

RowTemplate replaces the tree pane's default name-cell content entirely — here, a status dot (derived from Progress) plus the task name, instead of plain text.

API Reference

GanttChart

GanttTask

Field Type Description
IdstringStable identifier used to reconcile drag edits back into the caller's collection.
NamestringThe label rendered on the task bar and in the tree pane's name column.
StartDateTimeStart date (inclusive).
EndDateTimeEnd date.
ProgressintCompletion percentage, 0–100. Drives the progress fill and the progress-handle drag.
Dependenciesstring[]?Ids of tasks this task depends on. Rendered as routed arrows between bars.
CustomClassstring?Extra CSS class applied to the bar — use to colour-code milestones or delayed work.
IsMilestoneboolWhen true, renders as a diamond at the Start date. End is clamped to Start.
GroupLabelstring?Optional swim-lane label — cluster with GroupBy.
ParentIdstring?GanttChart-only: set to another task's Id to build real parent/child hierarchy and enable the tree pane by default.
IsRecurringboolMarks the bar as part of a series you generated yourself — see Styling hooks' data-recurring.

GanttUpdateResult / GanttUpdateAdjustment

The verdict OnTaskUpdate returns for every drag/resize/progress/create commit.

Value Effect
false / GanttUpdateResult.RejectRejects the edit outright — nothing commits, no callback fires, no TasksChanged.
true / GanttUpdateResult.AcceptCommits exactly the proposed Start/End/Progress.
GanttUpdateResult.AcceptWith(adjustment)Commits adjustment's Start/End/Progress instead of the raw proposal (any left null keeps the proposed value).

GanttViewMode

Value Description
QuarterDay6-hour columns — useful for hour-scale shift scheduling.
HalfDay12-hour columns.
DayOne column per day — the default.
WeekOne column per week.
MonthOne column per month — best for multi-quarter plans.
QuarterOne column per 3-month quarter — GanttChart-only.
YearOne column per year — best for roadmap-style views.

Styling hooks (data-*)

A rendered bar, grid cell, or drag ghost carries plain data-* attributes for its own state — no class-string parsing required. Boolean states are presence-only (the attribute is either there or it isn't, so [data-selected] is a valid selector on its own); data-progress is the one exception and carries the clamped 0–100 value.

Attribute Element Shape Meaning
data-selectedBarpresenceThe task's id is in SelectedIds (e.g. checked via a row checkbox).
data-draggingBarpresenceA move/resize/progress drag gesture is live on this bar (set by the drag engine, not by a re-render).
data-progressBar0–100The task's clamped completion percentage — the same value the progress fill's width uses.
data-completedBarpresenceProgress is exactly 100.
data-pastBarpresenceThe task's End is before "now" (the browser's current time, not the server's).
data-recurringBarpresenceGanttTask.IsRecurring is set — for a consumer generating its own repeating occurrences.
data-offHeader cell / canvas bandpresenceAn off-day column under MarkOffDays/OffDays — on the header date cell and the canvas tint behind it.
data-drop-invalidDrag ghostpresenceThe current drag position fails CanDrop — including while a verdict is still in flight (fail-closed).

One example per family — a boolean bar state, the value-carrying one, and the grid/drag hooks:

/* Boolean bar state — outline the selected task */
[data-selected] { outline: 2px solid var(--color-primary); }

/* Value-carrying — a completion badge past 80% */
[data-progress] { --p: attr(data-progress number); }
[data-progress]:is([data-completed]) { opacity: 0.7; }

/* Grid / drag ghost */
[data-off] { background: color-mix(in oklab, var(--color-muted) 60%, transparent); }
[data-drop-invalid] { border-color: var(--color-destructive); }
  • Scheduler — calendar-style event grid when you care about time-of-day rather than project phases.
  • Data Grid — tabular view of the same task data when a timeline isn't needed.
  • Gantt (Legacy) — the original SVG-based engine, kept for backward compatibility.