MicroGantt
Lightweight Gantt chart with schedules, task bars, drag-to-move, resize, dependency drawing, and collapsible groups.
JS: public/js/microgantt.js
CSS: public/js/microgantt.css
Version: 0.3.0
Quick start
Include the CSS and JS, then create a chart:
<link rel="stylesheet" href="/public/js/microgantt.css">
<script src="/public/js/microgantt.js"></script>
<div id="gantt"></div>
<script>
var chart = new MicroGantt('#gantt', {
schedules: [
{ id: 'sprint-1', name: 'Sprint 1', start: '2026-03-01', end: '2026-03-14', color: '#5D9288' }
],
tasks: [
{ id: 'PL-1', name: 'Design homepage', start: '2026-03-02', end: '2026-03-06', scheduleId: 'sprint-1', color: '#3B82F6', progress: 60 },
{ id: 'PL-2', name: 'Build API', start: '2026-03-05', end: '2026-03-10', scheduleId: 'sprint-1', dependencies: ['PL-1'] },
{ id: 'PL-3', name: 'Write docs', start: '2026-03-08', end: '2026-03-13' }
],
viewMode: 'week',
onTaskClick: function(task) { console.log('Clicked', task.id); },
onTaskResize: function(task, start, end) { console.log('Resized', task.id, start, end); },
onTaskMove: function(task, start, end) { console.log('Moved', task.id, start, end); },
onDependencyCreate: function(fromId, toId) { console.log('Dependency', fromId, '→', toId); }
});
</script>
Constructor
new MicroGantt(selector, options)
| Param | Type | Description |
|---|---|---|
selector |
string or HTMLElement |
CSS selector or DOM element for the container. |
options |
object |
Configuration object (see below). |
Options
| Option | Type | Default | Description |
|---|---|---|---|
schedules |
array |
[] |
Schedule (group) objects. |
tasks |
array |
[] |
Task objects. |
viewMode |
string |
'week' |
Time scale: 'day', 'week', or 'month'. |
rowHeight |
number |
38 |
Height of each row in pixels. |
barHeight |
number |
22 |
Height of task bars in pixels. |
scheduleBarHeight |
number |
10 |
Height of schedule (group) bars. |
labelWidth |
number |
280 |
Initial width of the left label panel (resizable). |
todayLine |
boolean |
true |
Show the red "Today" indicator line. |
onTaskClick |
function |
null |
(task) => {} — fired when a task bar or label is clicked. |
onTaskResize |
function |
null |
(task, newStart, newEnd) => {} — fired after dragging a task's right edge. |
onTaskMove |
function |
null |
(task, newStart, newEnd) => {} — fired after drag-moving a task bar. |
onDependencyCreate |
function |
null |
(fromId, toId) => {} — fired after drawing a dependency link. |
Schedule object
Schedules are group headers. Tasks with a matching scheduleId are nested under them and can be collapsed.
| Field | Type | Required | Description |
|---|---|---|---|
id |
string |
yes | Unique identifier. |
name |
string |
yes | Display name. |
start |
string |
yes | Start date (YYYY-MM-DD). |
end |
string |
yes | End date (YYYY-MM-DD). |
color |
string |
no | Bar color. Default: #5D9288. |
dependencies |
array |
no | Array of schedule/task IDs this schedule depends on. |
Task object
| Field | Type | Required | Description |
|---|---|---|---|
id |
string |
yes | Unique identifier (shown on the bar and label). |
name |
string |
yes | Display name. Also accepts title. |
start |
string |
yes | Start date (YYYY-MM-DD). |
end |
string |
yes | End date (YYYY-MM-DD). |
scheduleId |
string |
no | ID of the parent schedule. Also accepts schedule_id. |
color |
string |
no | Bar accent color. Default: #3B82F6. |
progress |
number |
no | Completion percentage (0–100). Renders a fill inside the bar. |
dependencies |
array |
no | Array of task/schedule IDs this task depends on. Draws dashed arrows. |
assignee |
string |
no | Initials or short name — shown as a colored avatar in the label. |
priority |
string |
no | Priority level (for your own use in callbacks). |
Tasks without valid start and end dates are filtered out.
Public methods
chart.update(schedules, tasks)
Replace all data and re-render.
chart.update(newSchedules, newTasks);
chart.setViewMode(mode)
Switch the time scale.
chart.setViewMode('month'); // 'day', 'week', or 'month'
chart.collapseAll() / chart.expandAll()
Collapse or expand all schedule groups.
chart.collapseAll();
chart.expandAll();
chart.render()
Re-render the chart with current in-memory data. Useful after modifying task data programmatically.
chart.render();
Internal data access
These internal properties can be used for live updates (e.g. reacting to side-panel changes):
| Property | Type | Description |
|---|---|---|
chart._taskMap |
object |
Map of task ID → parsed task object. |
chart._scheduleMap |
object |
Map of schedule ID → parsed schedule object. |
Each parsed task object has a dependencies array that can be modified, followed by chart.render() to update the arrows.
Interactions
Drag to move
Click and drag a task bar horizontally to change its dates. The onTaskMove callback fires on release.
Resize
Drag the right edge of a task bar to change the end date. The onTaskResize callback fires on release.
Dependency drawing
Hover a task bar to reveal a small circle on its right edge. Drag from that circle to another task bar to create a dependency. The onDependencyCreate callback fires when the link is made. Dependencies render as dashed arrows with arrowheads.
Collapsible groups
Click the ▸/▾ toggle on a schedule row to collapse or expand its child tasks.
Label panel resize
Drag the thin divider between the label panel and the chart to resize the label column (min 140px, max 500px).
View mode toolbar
Click Day, Week, or Month in the toolbar to switch time scales.
Usage in the Tasks app
The Tasks app uses MicroGantt in two views:
Timeline tab (schedule-grouped)
Shows tasks grouped under schedule rows. Tasks are nested under their schedule and can be collapsed. Rendered by tasks/partials/gantt_init.html.
new MicroGantt(el, {
viewMode: 'week',
schedules: [...], // All board schedules
tasks: [...], // All board tasks with start or due date
onTaskClick: function(task) { /* open task detail panel */ },
onTaskResize: function(task, newStart, newEnd) {
MicroAPI.put('/tasks/' + task.taskId, { start_date: newStart, due_date: newEnd });
},
onTaskMove: function(task, newStart, newEnd) {
MicroAPI.put('/tasks/' + task.taskId, { start_date: newStart, due_date: newEnd });
},
onDependencyCreate: function(fromId, toId) {
MicroAPI.put('/tasks/' + toId, { blocked_by: fromId });
}
});
Gantt tab (flat)
Shows all board tasks as a flat list — no schedule grouping. Rendered by tasks/partials/timeline_init.html.
new MicroGantt(el, {
viewMode: 'week',
schedules: [], // Empty — no grouping
tasks: [...], // All board tasks, scheduleId set to null
// Same callbacks as above
});
Persisting changes
Both views persist drag/resize/dependency changes via MicroAPI.put():
| Interaction | API call | Fields |
|---|---|---|
| Resize task bar | PUT /tasks/:id |
start_date, due_date |
| Move task bar | PUT /tasks/:id |
start_date, due_date |
| Draw dependency | PUT /tasks/:toId |
blocked_by (set to fromId) |
Dates are passed as YYYY-MM-DD strings and parsed server-side via date.fromisoformat().
Live dependency sync
When a task's blocked_by is changed from the side panel (task detail view), the Gantt/Timeline updates live without a full reload. The side panel dispatches a custom event:
// Dispatched by clearBlocker() / pickBlocker() in the task detail panel
document.dispatchEvent(new CustomEvent('gantt:dependency-changed', {
detail: { taskId: 'PL-2', blockedBy: 'PL-1' } // or blockedBy: '' to clear
}));
Both Gantt and Timeline listen for this event:
document.addEventListener('gantt:dependency-changed', function(e) {
var task = gantt._taskMap[e.detail.taskId];
if (task) {
task.dependencies = e.detail.blockedBy ? [e.detail.blockedBy] : [];
gantt.render();
}
});
Single-date tasks
Tasks with only start_date or only due_date (but not both) are still rendered. The missing date is filled with the available one, producing a single-day bar on the chart.
CSS classes
All classes are prefixed with mg-.
| Class | Element | Purpose |
|---|---|---|
.mg-root |
container | Outer wrapper — sets font, border, background. |
.mg-toolbar |
div |
Top toolbar with view mode buttons. |
.mg-view-btn |
button |
Day/Week/Month toggle button. .mg-active for current. |
.mg-labels |
div |
Left label panel (scrollable, resizable). |
.mg-label-row |
div |
Single label row. |
.mg-label-schedule |
.mg-label-row |
Schedule (group header) row. |
.mg-fold-toggle |
span |
Collapse/expand arrow. |
.mg-label-id |
span |
Task ID badge. |
.mg-label-name |
span |
Task name (truncated). |
.mg-label-avatar |
span |
Colored circle with assignee initials. |
.mg-label-resizer |
div |
Draggable divider between labels and chart. |
.mg-chart-outer |
div |
Scrollable chart viewport. |
.mg-bar |
div |
Task bar. |
.mg-bar-schedule |
.mg-bar |
Schedule (group) bar — thinner. |
.mg-bar-progress |
div |
Progress fill inside a task bar. |
.mg-bar-label |
span |
Task ID text on the bar. |
.mg-resize-handle |
div |
Right-edge drag handle for resizing. |
.mg-dep-connector |
div |
Circle for starting a dependency drag. |
.mg-dep-from |
.mg-bar |
Highlighted source during dependency drawing. |
.mg-dep-target |
.mg-bar |
Highlighted target during dependency drawing. |
.mg-today |
div |
Red vertical "Today" line. |
.mg-weekend |
div |
Weekend column shading. |
.mg-dep-svg |
svg |
SVG layer for dependency arrows. |
CSS custom properties
MicroGantt reads these CSS variables (with fallbacks):
| Variable | Fallback | Used for |
|---|---|---|
--text-primary |
#414244 |
Labels, bar text |
--text-secondary |
#6B6D6F |
Button text |
--text-muted |
#9B9DA0 |
Header, IDs, muted text |
--surface |
#fff |
Backgrounds |
--bg |
#F7F6F3 |
Hover backgrounds |
--bg-sunken |
#EFEEE9 |
Schedule rows, weekends |
--bs-border-color |
#E2E0DB |
Borders |
--brand |
#5D9288 |
Active view button, resizer hover |