Gantt Chart
import { Gantt, type GanttTask, type GanttDependency } from '@absoluteui/components/gantt';import '@absoluteui/components/gantt/style.css';Using Angular? See Gantt Chart for Angular.
What it does
Section titled “What it does”A project schedule. A task tree grid (name, start, end, duration, and optionally progress, resources, float) sits beside a timeline of bars with summary tasks, milestones, progress, baselines, dependency connectors, the critical path, non-working days, and today. An optional histogram shows each resource’s daily load against its capacity.
Tasks are scheduled in working days of a Business Calendar. Dependencies (finish-to-start, start-to-start, finish-to-finish, start-to-finish, with lag or lead in working days) push successors later but never before their requested start (forward scheduling). Manual tasks keep their start and report violated dependencies. A backward pass gives each task’s total float; tasks without float form the critical path.
Editing (with editable): drag a bar to move it, its end to resize it, or its link handle onto another bar to link them. Keyboard: Ctrl/Cmd+Left/Right moves the focused task by a working day, Shift+Left/Right changes its duration. The toolbar offers the same actions plus Link tasks (then Enter on the successor). Every change is dispatched first as the cancelable aui-task-change with the tasks, dependencies, and the new schedule, and is undoable. The engine (scheduleGantt, resourceLoad, createsCycle, assertGantt) is pure and runs without DOM.
When to use
Section titled “When to use”- Planning and tracking projects with dependent tasks, milestones, and deadlines.
- Finding the critical path and the float of each task after a change.
- Comparing the current schedule with a baseline, and spotting over-allocated resources.
When not to use
Section titled “When not to use”- Calendars of meetings and appointments with times of day: use Scheduler.
- Workflow boards without dates: use Kanban.
- Simple date ranges on a few rows: use a timeline view of Scheduler or a table.
Examples
Section titled “Examples”A project plan with dependencies and a milestone
Section titled “A project plan with dependencies and a milestone”import { plainDate } from '@absoluteui/core';import { Gantt, type GanttDependency, type GanttTask } from '@absoluteui/components/gantt';
const tasks: GanttTask[] = [ { id: 'design', parentId: null, label: 'Design', start: plainDate(2026, 9, 28), duration: 5 }, { id: 'build', parentId: null, label: 'Build', start: plainDate(2026, 9, 28), duration: 10, progress: 20 }, { id: 'launch', parentId: null, label: 'Launch', start: plainDate(2026, 9, 28), duration: 0 },];const dependencies: GanttDependency[] = [ { id: 'd1', from: 'design', to: 'build' }, { id: 'd2', from: 'build', to: 'launch', lag: 2 },];
const host = document.createElement('div');document.body.append(host);const gantt = Gantt.create(host, { label: 'Website relaunch', tasks, dependencies, columns: ['name', 'start', 'end', 'duration', 'progress'] });document.body.dataset.finish = gantt.schedule.finish ? `${String(gantt.schedule.finish.month)}/${String(gantt.schedule.finish.day)}` : '';Editing with a holiday calendar, saving every change
Section titled “Editing with a holiday calendar, saving every change”import { plainDate } from '@absoluteui/core';import { Gantt, type GanttTask, type GanttTaskChangeDetail } from '@absoluteui/components/gantt';
let saved: GanttTask[] = [ { id: 'phase', parentId: null, label: 'Phase 1', start: plainDate(2026, 10, 1), duration: 0 }, { id: 'a', parentId: 'phase', label: 'Research', start: plainDate(2026, 10, 1), duration: 3 }, { id: 'b', parentId: 'phase', label: 'Prototype', start: plainDate(2026, 10, 1), duration: 4, manual: true },];
const host = document.querySelector<HTMLElement>('#plan');if (host) { Gantt.create(host, { label: 'Phase plan', tasks: saved, dependencies: [{ id: 'ab', from: 'a', to: 'b' }], editable: true, scale: 'day', calendar: { workingDays: [1, 2, 3, 4, 5], holidays: [{ date: plainDate(2026, 10, 5), name: 'Company day' }] }, // Prototype dates are owned by another team. canEdit: (task) => task.id !== 'b', }); host.addEventListener('aui-task-change', (event) => { const detail = (event as CustomEvent<GanttTaskChangeDetail>).detail; if (detail.schedule.finish && detail.schedule.finish.month > 11) event.preventDefault(); else saved = detail.tasks; });}Baselines, resources, and the load histogram
Section titled “Baselines, resources, and the load histogram”import { plainDate } from '@absoluteui/core';import { Gantt } from '@absoluteui/components/gantt';
const host = document.createElement('div');document.body.append(host);const gantt = Gantt.create(host, { label: 'Migration', tasks: [ { id: 'plan', parentId: null, label: 'Plan', start: plainDate(2026, 10, 5), duration: 3, assignments: [{ resourceId: 'ana' }], baseline: { start: plainDate(2026, 10, 5), end: plainDate(2026, 10, 6) } }, { id: 'move', parentId: null, label: 'Move data', start: plainDate(2026, 10, 6), duration: 4, assignments: [{ resourceId: 'ana', units: 50 }, { resourceId: 'ben' }] }, ], resources: [{ id: 'ana', label: 'Ana' }, { id: 'ben', label: 'Ben', capacity: 80 }], columns: ['name', 'start', 'end', 'resources', 'float'], showHistogram: true,});const overloaded = gantt.resourceLoad().filter((r) => r.overDays > 0).map((r) => r.resourceId);host.dataset.overloaded = overloaded.join(',');Schedule on a server or in a worker (no DOM)
Section titled “Schedule on a server or in a worker (no DOM)”import { plainDate } from '@absoluteui/core';import { createBusinessCalendar } from '@absoluteui/components/business-calendar';import { assertGantt, scheduleGantt, type GanttDependency, type GanttTask } from '@absoluteui/components/gantt';
const tasks: GanttTask[] = [ { id: 'a', parentId: null, label: 'Pour foundation', start: plainDate(2026, 10, 1), duration: 2 }, { id: 'b', parentId: null, label: 'Cure', start: plainDate(2026, 10, 1), duration: 5 },];const dependencies: GanttDependency[] = [{ id: 'ab', from: 'a', to: 'b', type: 'FS', lag: 1 }];assertGantt(tasks, dependencies, undefined);const schedule = scheduleGantt(tasks, dependencies, createBusinessCalendar({ workingDays: [1, 2, 3, 4, 5, 6] }));const cure = schedule.tasks.get('b');document.body.dataset.cure = cure ? `${String(cure.start.day)}-${String(cure.end.day)}, critical ${String(cure.critical)}` : '';Day scale and taller rows everywhere
Section titled “Day scale and taller rows everywhere”import { configureAbsoluteUI } from '@absoluteui/core';
configureAbsoluteUI({ components: { gantt: { scale: 'day', rowHeight: 44, historyLimit: 100 } } });import { plainDate } from '@absoluteui/core';import { Gantt, type GanttTask, type GanttTaskChangeDetail } from '@absoluteui/components/gantt';import '@absoluteui/components/gantt/style.css';
let saved: GanttTask[] = [ { id: 'design', parentId: null, label: 'Design', start: plainDate(2026, 10, 5), duration: 5 }, { id: 'build', parentId: null, label: 'Build', start: plainDate(2026, 10, 5), duration: 10 }, { id: 'launch', parentId: null, label: 'Launch', start: plainDate(2026, 10, 5), duration: 0 },];const host = document.querySelector<HTMLElement>('#plan');if (host) { Gantt.create(host, { label: 'Website relaunch', tasks: saved, dependencies: [{ id: 'd1', from: 'design', to: 'build' }, { id: 'd2', from: 'build', to: 'launch' }], editable: true, calendar: { holidays: [{ date: plainDate(2026, 12, 25), name: 'Christmas Day', yearly: true }] }, }); host.addEventListener('aui-task-change', (event) => { saved = (event as CustomEvent<GanttTaskChangeDetail>).detail.tasks; });}More usage
Section titled “More usage”See section 33 and metadata/gantt/examples.json: a plan with dependencies and a milestone, editing with a holiday calendar, baselines and resources with the histogram, the engine without DOM, global configuration.
Anatomy
Section titled “Anatomy”<div class="aui-gantt [--editable] [--linking] [--day|--week|--month] [--rtl]"> (consumer host) <div class="aui-gantt__toolbar" role="group" aria-label="{label} controls"> <button class="aui-gantt__tool" data-aui-action="zoomOut|zoomIn|today|earlier|later|shorten|lengthen|link|undo|redo"> <div class="aui-gantt__body"> (scrolls both ways) <div class="aui-gantt__table" role="treegrid" aria-label="{label}" aria-rowcount aria-colcount> (sticky at inline start) <div class="aui-gantt__head-group" role="rowgroup"><div class="aui-gantt__head" role="row"> columnheaders <div class="aui-gantt__rows" role="rowgroup"> (virtual rows) <div class="aui-gantt__row [--summary] [--critical]" role="row" data-aui-task="build" aria-rowindex="5" aria-level="1" aria-setsize="4" aria-posinset="2" [aria-expanded] tabindex="0"> <div class="aui-gantt__cell aui-gantt__cell--name" role="gridcell"> <span class="aui-gantt__toggle" aria-hidden="true"> <span class="aui-gantt__name">Build</span> <span class="aui-gantt__badge aui-gantt__badge--critical">Critical</span> <span class="aui-gantt__hidden"> Depends on Design (finish to start).</span> <div class="aui-gantt__cell aui-gantt__cell--start" role="gridcell">Oct 5, 2026</div> ... <div class="aui-gantt__chart" aria-hidden="true"> <div class="aui-gantt__scale"><div class="aui-gantt__tier"><span class="aui-gantt__tick">... <div class="aui-gantt__canvas"> <div class="aui-gantt__shade"><div class="aui-gantt__off"> (non-working days) <div class="aui-gantt__today"> <svg class="aui-gantt__links"><path class="aui-gantt__dependency [--critical] [--violated]"> <div class="aui-gantt__bars"> <div class="aui-gantt__bar aui-gantt__bar--c1 [--summary|--milestone|--critical|--manual|--focus]" data-aui-task="build"> <span class="aui-gantt__fill"><span class="aui-gantt__progress"></span></span> <span class="aui-gantt__bar-label">Build</span> <span class="aui-gantt__resize"> <span class="aui-gantt__link-handle"> <span class="aui-gantt__baseline"> <div class="aui-gantt__histogram"> (showHistogram) <div class="aui-gantt__histogram-title" role="heading" aria-level="3">Resource load</div> <div class="aui-gantt__load-row"><div class="aui-gantt__load-label">Ana <span>Peak 150%, 2 days over capacity</span></div> <div class="aui-gantt__load-track" aria-hidden="true"><span class="aui-gantt__load [--over]"> <p class="aui-gantt__instructions">...</p> (visually hidden)API reference
Section titled “API reference”Factory
Section titled “Factory”Gantt.create(host: HTMLElement, options: GanttOptions): Gantt; scheduleGantt(tasks, dependencies, calendar: BusinessCalendarEngine, index?: WorkIndex): GanttSchedule; resourceLoad(tasks, schedule, resources, calendar, range: { start: PlainDate; end: PlainDate }): GanttResourceLoad[]; createsCycle(dependencies, from, to): boolean; assertGantt(tasks, dependencies, resources): voidGlobal configuration key: gantt (see Configuration).
Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
label |
string |
Accessible name of the tree grid; the toolbar is named ‘{label} controls’. Non-empty. Required. | |
tasks |
readonly GanttTask[] |
Tasks: { id, parentId (summary task id or null), label, start (requested start, PlainDate), duration (working days, 0 = milestone), progress? (0..100), manual?, assignments? ({ resourceId, units? percent }), baseline? ({ start, end } inclusive), color? (1..8), readOnly?, collapsed? }. Tasks with children are summary tasks (their start and duration are ignored). Order within a parent is the array order. Validated (GANTT_OPTIONS). Replacing it clears the undo history. Required. | |
dependencies |
readonly GanttDependency[] |
{ id, from (predecessor), to (successor), type? (‘FS’ default, ‘SS’, ‘FF’, ‘SF’), lag? (working days, negative = lead) }. Leaf tasks only, one per pair, no cycles (the error names the cycle). | |
resources |
readonly GanttResource[] |
{ id, label, capacity? (percent per working day, default 100) }; assignments must reference them. | |
calendar |
BusinessCalendarDefinition |
Working days, holidays, and exceptions (default Monday to Friday). Durations and lags count its working days; non-working days are shaded. | |
editable |
boolean |
false |
Pointer, keyboard, and toolbar editing (move, resize, link). |
columns |
readonly GanttColumnKey[] |
"['name', 'start', 'end', 'duration']" |
Grid columns: ‘name’ first, then any of ‘start’, ‘end’, ‘duration’, ‘progress’, ‘resources’, ‘float’ (unique). |
showCritical |
boolean |
true |
Mark critical tasks (badge, hatched bar, red connectors). |
showBaselines |
boolean |
true |
Draw baselines and describe baseline variance in the grid. |
showHistogram |
boolean |
false |
Show the resource load histogram below the chart (needs resources): daily load per resource with peak and over-capacity days as text. |
today |
PlainDate |
Date of the today line and the Go to today button (default: the device’s local date). | |
canEdit |
(task: Readonly<GanttTask>) => boolean |
Veto edits of a task (also as a link successor). Summary and read-only tasks are never edited. | |
scale |
'day' | 'week' | 'month' |
"week" |
Timeline scale (32, 16, or 5 CSS px per day); also changed by the zoom buttons and setScale(). Globally configurable. |
rowHeight |
number |
36 |
Row height in CSS px (24..96). Rows have a fixed height (virtual rows). Globally configurable. |
historyLimit |
number |
50 |
Undo depth (0..500). Globally configurable. |
locale |
string |
"en-US" |
Dates, numbers, the first day of the week (week scale), plural forms, and messages. Globally configurable. Inherited from common configuration. |
direction |
'ltr' | 'rtl' |
"ltr" |
Mirrors the timeline and swaps ArrowLeft/ArrowRight. Globally configurable. Inherited from common configuration. |
Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
host |
HTMLElement |
Consumer host. |
element |
HTMLDivElement |
The tree grid (role=treegrid). |
tasks |
GanttTask[] |
Every task (copies) with requested starts. |
dependencies |
GanttDependency[] |
Every dependency (copies). |
schedule |
GanttSchedule |
Scheduled dates, float, critical flags, violations, and variance per task; project start and finish; critical ids. |
businessCalendar |
BusinessCalendarEngine |
The working-day engine in use. |
scale |
GanttScale |
Current scale. |
editable |
boolean |
Whether editing is on. |
expanded |
string[] |
Expanded summary task ids. |
canUndo |
boolean |
A change can be undone. |
canRedo |
boolean |
An undone change can be redone. |
Methods
Section titled “Methods”| Method | Description |
|---|---|
update(options: Partial<GanttOptions>): void |
Merge and apply options; new tasks or dependencies clear the history (expansion of known summaries is kept). |
setScale(scale: GanttScale): void |
Change the scale, keeping the first visible date; emits aui-scale-change. |
setExpanded(id: string, expanded: boolean): void |
Expand or collapse a summary task (emits aui-expand-change). |
expandAll(): void |
Expand every summary task. |
collapseAll(): void |
Collapse every summary task. |
scrollToTask(id: string, options?: { focus?: boolean }): void |
Expand the ancestors, scroll the row and bar into view, and focus the row (unless focus is false). |
scrollToDate(date: PlainDate): void |
Center the timeline on a date. |
focusTask(id: string): void |
scrollToTask with focus. |
moveTask(id: string, start: PlainDate): boolean |
Change the requested start (next working day). Emits aui-task-change; false when refused or cancelled. |
setDuration(id: string, duration: number): boolean |
Change the duration in working days (0 = milestone). |
addDependency(dependency: GanttDependency): boolean |
Add a dependency (validated; throws GANTT_OPTIONS for cycles or summary tasks); false when the event is cancelled. |
removeDependency(id: string): boolean |
Remove a dependency. |
resourceLoad(range?: { start: PlainDate; end: PlainDate }): GanttResourceLoad[] |
Daily load per resource (default: the timeline range). |
undo(): boolean |
Undo the last change (emits aui-task-change with reason ‘undo’). |
redo(): boolean |
Redo the last undone change. |
destroy(): void |
Remove listeners and the rendered chart. |
Events
Section titled “Events”| Event | Detail | Bubbles | Cancelable | Description |
|---|---|---|---|---|
aui-task-change |
{ reason: 'move' | 'resize' | 'link' | 'unlink' | 'undo' | 'redo'; changes: GanttTaskChange[]; dependency: GanttDependency | null; tasks: GanttTask[]; dependencies: GanttDependency[]; schedule: GanttSchedule } |
Yes | Yes | Before a change is applied; preventDefault() keeps the previous state. |
aui-task-activate |
{ id: string; task: GanttTask } |
Yes | No | Enter on a row. |
aui-expand-change |
{ id: string; expanded: boolean } |
Yes | No | A summary task was expanded or collapsed. |
aui-scale-change |
{ scale: GanttScale } |
Yes | No | The scale changed (zoom buttons or setScale). |
Content areas
Section titled “Content areas”| Area | Description |
|---|---|
none |
Rows and bars render task data; no custom content slots. |
CSS classes
Section titled “CSS classes”All rules live in the aui.components cascade layer, so application styles override them without specificity battles.
| Class | Purpose |
|---|---|
aui-gantt | --editable | --linking | --day | --week | --month | --rtl |
Host and modifiers; –aui-gantt-table-width, –aui-gantt-height, –aui-gantt-tier size the chart (–aui-gantt-row and –aui-gantt-day are set by the component). |
aui-gantt__toolbar | __tool |
Toolbar. |
aui-gantt__body | __table | __head-group | __head | __rows | __row (--summary, --critical, --link-source) | __cell (--name, --start, --end, --duration, --progress, --resources, --float) | __toggle | __name | __badge (--milestone, --critical) |
Tree grid. |
aui-gantt__chart | __scale | __tier | __tick (--off) | __canvas | __shade | __off | __today | __links | __dependency (--critical, --violated) | __arrow |
Timeline. |
aui-gantt__bars | __bar (--c1..--c8, --summary, --milestone, --critical, --manual, --editable, --focus, --link-source, --dragging, --drop, --no-drop) | __fill | __progress | __bar-label | __baseline | __resize | __link-handle |
Bars. |
aui-gantt__histogram | __histogram-title | __load-row | __load-label | __load-name | __load-summary | __load-track | __load (--over) |
Resource histogram. |
Icon slots
Section titled “Icon slots”| Slot | Default icon |
|---|---|
zoom out / zoom in |
zoom-out / zoom-in |
today |
locate |
earlier / later |
chevron-left / chevron-right |
shorten / lengthen |
minus / plus |
link |
link |
undo / redo |
undo / redo |
expand |
chevron-right / chevron-down |
Design tokens
Section titled “Design tokens”Tokens this stylesheet reads (verified in CI). Override them in a theme or with the Theme Designer.
--aui-border-width | --aui-border-width-strong | --aui-color-border | --aui-color-border-strong | --aui-color-chart-1 | --aui-color-chart-2 | --aui-color-chart-3 | --aui-color-chart-4 | --aui-color-chart-5 | --aui-color-chart-6 | --aui-color-chart-7 | --aui-color-chart-8 | --aui-color-chart-axis | --aui-color-error-fg | --aui-color-focus-ring | --aui-color-hover | --aui-color-primary | --aui-color-selected | --aui-color-selected-text | --aui-color-surface | --aui-color-surface-sunken | --aui-color-text | --aui-color-text-disabled | --aui-color-text-muted | --aui-color-warning-fg | --aui-duration-fast | --aui-easing-standard | --aui-focus-ring-offset | --aui-focus-ring-width | --aui-font-family-sans | --aui-font-size-sm | --aui-font-size-xs | --aui-font-weight-medium | --aui-font-weight-semibold | --aui-icon-size-sm | --aui-line-height-tight | --aui-radius-md | --aui-radius-pill | --aui-radius-sm | --aui-shadow-md | --aui-space-1 | --aui-space-2 | --aui-touch-target-min
TypeScript definitions
Section titled “TypeScript definitions”type GanttDependencyType = 'FS' | 'SS' | 'FF' | 'SF';interface GanttAssignment { resourceId: string; units?: number }interface GanttBaseline { start: PlainDate; end: PlainDate }interface GanttTask { id: string; parentId: string | null; label: string; start: PlainDate; duration: number; progress?: number; manual?: boolean; assignments?: readonly GanttAssignment[]; baseline?: GanttBaseline; color?: GanttColor; readOnly?: boolean; collapsed?: boolean }interface GanttDependency { id: string; from: string; to: string; type?: GanttDependencyType; lag?: number }interface GanttResource { id: string; label: string; capacity?: number }interface GanttScheduledTask { id: string; start: PlainDate; end: PlainDate; duration: number; summary: boolean; milestone: boolean; totalFloat: number; critical: boolean; driven: boolean; violations: readonly string[]; variance: number | null }interface GanttSchedule { tasks: ReadonlyMap<string, GanttScheduledTask>; start: PlainDate | null; finish: PlainDate | null; critical: readonly string[] }interface GanttResourceLoad { resourceId: string; days: readonly { date: PlainDate; load: number; capacity: number; over: boolean }[]; overDays: number; peak: number }type GanttScale = 'day' | 'week' | 'month';type GanttColumnKey = 'name' | 'start' | 'end' | 'duration' | 'progress' | 'resources' | 'float';interface GanttTaskChange { id: string; start?: PlainDate; duration?: number }interface GanttTaskChangeDetail { reason: 'move' | 'resize' | 'link' | 'unlink' | 'undo' | 'redo'; changes: GanttTaskChange[]; dependency: GanttDependency | null; tasks: GanttTask[]; dependencies: GanttDependency[]; schedule: GanttSchedule }Accessibility
Section titled “Accessibility”Pattern: WAI-ARIA APG Treegrid with row focus: rows carry aria-level, aria-setsize, aria-posinset, aria-expanded (summary tasks), and aria-rowindex (virtual rows); one roving tab stop. The grid is the accessible surface: every value a bar shows (dates, duration, milestone, critical, dependencies, violations, baseline variance) is text in its row. The timeline and histogram tracks are aria-hidden pointer surfaces with keyboard and toolbar equivalents for every action (WCAG 2.5.7).
Keyboard
Section titled “Keyboard”| Key | Context | Action |
|---|---|---|
| Tab / Shift+Tab | Chart | Toolbar buttons, then the grid (one tab stop: the focused row). |
| ArrowDown / ArrowUp | Row focused | Next / previous visible task (the grid scrolls; virtual rows render). |
| PageDown / PageUp, Home / End | Row focused | One page down / up; first / last task. |
| ArrowRight (ArrowLeft in RTL) | Row focused | Expand a collapsed summary; on an expanded one, move to its first child. |
| ArrowLeft (ArrowRight in RTL) | Row focused | Collapse an expanded summary; otherwise move to the parent. |
| Enter | Row focused | Activate (aui-task-activate); while linking, make this task the successor (or remove the existing link between the two). |
| Ctrl/Cmd+ArrowRight / Ctrl/Cmd+ArrowLeft | Row focused (editable) | Move the task one working day later / earlier (reading direction in RTL). Announces the new dates, or that dependencies prevent an earlier start. |
| Shift+ArrowRight / Shift+ArrowLeft | Row focused (editable) | Lengthen / shorten by one working day (at least one day). |
| Ctrl/Cmd+Z, Ctrl/Cmd+Shift+Z or Ctrl/Cmd+Y | Row focused (editable) | Undo / redo. |
| Escape | Linking | Cancel linking. |
| Element | Role |
|---|---|
| toolbar <div> | group, named ‘{label} controls’ |
| toolbar <button>s | button (native); Link is a toggle (aria-pressed) |
| grid <div> | treegrid, named by aria-label, described by the instructions |
| header and body groups | rowgroup |
| header row / cells | row / columnheader |
| task row / cells | row / gridcell |
| timeline, connectors, bars | none (aria-hidden=true) |
| histogram title / summaries | heading (level 3) / text; tracks are aria-hidden |
ARIA attributes
Section titled “ARIA attributes”| Attribute | Element | Value |
|---|---|---|
aria-label / aria-describedby |
treegrid | label / visually hidden instructions |
aria-rowcount / aria-colcount |
treegrid | Visible rows + 1 (header) / column count |
aria-rowindex |
row | 1-based index including the header (rows are virtual) |
aria-level / aria-setsize / aria-posinset |
task row | Depth, siblings, position |
aria-expanded |
summary row | true / false (absent on leaf tasks) |
aria-colindex |
cells | 1-based column |
tabindex |
task row | 0 on the focused row, -1 on the others |
aria-pressed / aria-disabled |
toolbar buttons | Link while picking a successor / true when an action is not possible (buttons stay focusable) |
live region |
shared live regions | Polite: new dates after a change, scale, undone, redone, linking cancelled. Assertive: linking instructions, linked, unlinked, refused, cannot be changed, limited by dependencies. |
One roving tab stop over the rows; the focused row stays rendered while the grid scrolls (virtual rows). Collapsing a summary moves focus to it from a hidden child. Changes keep focus on the edited row; toolbar actions apply to the focused row and leave focus on the button. Clicking a bar focuses its row.
WCAG 2.2 success criteria addressed
Section titled “WCAG 2.2 success criteria addressed”| Criterion | Level | Note |
|---|---|---|
| 1.3.1 Info and Relationships | A | |
| 1.4.1 Use of Color | A | |
| 1.4.10 Reflow | AA | two-dimensional chart scrolls in its own container |
| 1.4.11 Non-text Contrast | AA | |
| 2.1.1 Keyboard | A | |
| 2.1.4 Character Key Shortcuts | A | only modifier shortcuts |
| 2.4.3 Focus Order | A | |
| 2.4.7 Focus Visible | AA | |
| 2.5.7 Dragging Movements | AA | |
| 2.5.8 Target Size (Minimum) | AA | |
| 4.1.2 Name, Role, Value | A | |
| 4.1.3 Status Messages | AA |
Automated test results: Accessibility and compliance.
Notes and known caveats
Section titled “Notes and known caveats”- Critical tasks are marked with the text ‘Critical’ in the grid and a hatched bar; milestones with ‘Milestone’.
- Dependencies and baseline variance are visually hidden text in the name cell, read with the row.
- The histogram’s peak load and over-capacity days are visible text next to each resource.
- Pointer drags are not announced until the change is applied.
- Manual screen-reader verification (NVDA, JAWS, VoiceOver) is pending.
Behavior
Section titled “Behavior”States
Section titled “States”Row focused; summary expanded or collapsed; critical, milestone, manual, read-only task; violated dependency; baseline; linking; dragging (move, resize, link) over a valid or invalid target; day, week, or month scale; histogram shown.
State transitions
Section titled “State transitions”| From | Trigger | To |
|---|---|---|
| row focused | Ctrl/Cmd+Arrow, toolbar Earlier/Later, bar drag | aui-task-change (move) -> rescheduled; announced |
| row focused | Shift+Arrow, toolbar Shorten/Lengthen, end drag | aui-task-change (resize) -> rescheduled |
| row focused | toolbar Link | linking (source marked) |
| linking | Enter or click on another task | linked (link), or unlinked when the pair is linked, or refused (cycle, summary) |
| linking | Escape, Link again, Enter on the source | cancelled |
| any change | preventDefault() on aui-task-change |
unchanged |
| changed | Ctrl/Cmd+Z / Undo | previous tasks and dependencies (undo) |
Accessibility notes
Section titled “Accessibility notes”- Every pointer action has a keyboard and toolbar equivalent (WCAG 2.5.7); shortcuts use modifiers (2.1.4).
- Critical tasks and milestones are labelled with text; dependencies (“Depends on Design (finish to start).”) and baseline variance (“2 working days behind baseline.”) are visually hidden text read with the row.
- Critical bars use a hatch pattern and a thicker border, not color alone.
- Manual screen-reader verification (NVDA, JAWS, VoiceOver) is pending.
Responsive behavior
Section titled “Responsive behavior”The body has a fixed block size (--aui-gantt-height) and scrolls in two dimensions (WCAG 1.4.10 exception) while the page reflows at 320 px. The grid stays at the inline start while the timeline scrolls; in containers narrower than 40rem it scrolls away with the timeline. Headers are sticky. Toolbar buttons meet touch-target-min; bars and handles use touch-action: none.
Right-to-left
Section titled “Right-to-left”direction: 'rtl' mirrors the timeline (later dates to the left, mirrored connectors) and swaps ArrowLeft / ArrowRight for expand, collapse, moving, and resizing (the arrow toward later dates moves later).
Theming
Section titled “Theming”Bars are tints of color-chart-1..8 with solid borders and progress fills; critical bars add a color-error-fg border and hatch; manual tasks have dashed borders; summaries are color-text brackets; milestones are diamonds; baselines are thin color-text-muted bars. Forced colors: Canvas/CanvasText bars, Mark for critical, Highlight for focus and the link source, hatched non-working days.
Global configuration
Section titled “Global configuration”configureAbsoluteUI({ components: { gantt: { scale: 'day', rowHeight: 44, historyLimit: 100 } } });Global options: scale, rowHeight, historyLimit, plus inherited locale and direction.
Component configuration
Section titled “Component configuration”Instance options override global defaults. All options are dynamic through update(); tasks and dependencies clear the undo history; calendar reschedules.
Timezones
Section titled “Timezones”Dates are PlainDate values without a timezone; durations and lags count working days of the calendar. The default today is the device’s local date; pass today for a fixed date (for example the server’s date).
Toolbar: zoom-out, zoom-in, locate (today), chevron-left / chevron-right (earlier / later), minus / plus (shorten / lengthen), link, undo, redo. Expand: chevron-right (chevron-left in RTL) / chevron-down.
Security
Section titled “Security”Text renders through textContent. Options are validated (GANTT_OPTIONS) before use: unique ids, known parents and resources, no parent cycles, dependencies between leaf tasks, one per pair, and no dependency cycles (the message names the cycle). Positions and sizes are written through the CSSOM; connectors are SVG paths built from numbers (CSP-safe).
Data handling
Section titled “Data handling”No persistence, network access, or telemetry. Changes are reported through aui-task-change for the application to save: tasks (requested starts and durations), dependencies, and schedule (computed dates). Store the requested starts; do not write scheduled dates back into start (see anti-patterns).
Performance
Section titled “Performance”Scheduling is linear in tasks plus dependencies (topological order, forward and backward passes) on a working-day index that maps dates to consecutive integers in constant time. Rows have a fixed height and only the rows in view (plus an overscan and the focused row) are rendered, with their bars and the connectors that touch them. Budgets (e2e): create with 2,000 tasks and 1,500 dependencies < 150 ms; a keyboard move with 2,000 tasks < 60 ms; scheduleGantt for 10,000 tasks < 80 ms.
Supported data scale
Section titled “Supported data scale”Tested with 2,000 tasks in the chart and 10,000 in the engine. Timeline columns are not virtualized: several years on the day scale render long scales (use the week or month scale).
Edge cases
Section titled “Edge cases”- A start on a non-working day moves to the next working day.
- Moving an auto-scheduled task earlier than its dependencies allow keeps it where it is and announces why.
- Manual tasks keep their start; unmet dependencies are dashed connectors and “Dependency not met” text.
- A summary task spans its children, ending on a trailing milestone’s date; summaries cannot be edited or linked.
- Linking two tasks that are already linked (either direction) removes the link.
- Negative lags (leads) can start a successor before its predecessor ends.
- Collapsing a summary moves focus from a hidden child to the summary.
Errors
Section titled “Errors”| Code | Category | Cause |
|---|---|---|
GANTT_OPTIONS |
configuration | Empty label; invalid tasks (ids, labels, dates, durations, progress, colors, baselines, assignments), parent cycles, unknown parents or resources; invalid dependencies (unknown or summary tasks, self links, duplicate pairs, invalid types or lags, cycles); invalid columns or flags; methods called with unknown ids. |
BUSINESS_CALENDAR_DEFINITION |
configuration | Invalid calendar. |
BUSINESS_CALENDAR_NO_WORKING_DAYS |
runtime | The calendar has no working day at all. |
A failed construction leaves the host untouched.
Known limitations
Section titled “Known limitations”- Whole working days only (no hours).
- Dependencies between leaf tasks only.
- One constraint type: start no earlier than the requested start.
- Resource load is shown, not leveled.
- Progress is not edited in the chart; pointer drags are announced only when applied.
- Manual screen-reader verification is pending.
Unsupported scenarios
Section titled “Unsupported scenarios”- Adding, deleting, renaming, indenting, or reordering tasks inside the chart.
- Several calendars (per resource or task).
- Printing and export; split, recurring, or cost-tracked tasks.