Interaction
Drag & Drop
When editing is enabled, users can interact with the chart using drag gestures:
- Move tasks — drag a task bar to change its start/end dates.
- Resize tasks — drag the left or right edge to change duration.
- Set progress — drag the progress handle inside a task bar.
- Create links — drag from a connector dot on one task to another.
- Move milestones — drag a milestone diamond to a new date.
// Enable or disable editing
gantt.canEdit = true; // default
gantt.canEdit = false; // read-only modeSelection & Editing
Users can select tasks by clicking rows in the sheet or task bars in the chart. Cell values can be edited inline.
// Get selected tasks
const selected = gantt.selectedTasks;
// Clear selection
gantt.sheet.clearSelection();
// Listen for editing events
gantt.events.sheetCellEditing$.subscribe(editing => {
if (editing) {
console.log('Editing', editing.item.name, editing.column.code);
}
});
// Click on task bar
gantt.events.taskClick$.subscribe(({ task }) => {
showTaskDetails(task);
});
// Double-click on task bar
gantt.events.taskDblClick$.subscribe(({ task }) => {
openTaskDialog(task);
});Tooltips
When users hover over a task bar in the chart, a tooltip automatically appears showing task details — name, start/end dates, duration, progress, and assigned resources. Tooltips are enabled by default and require no configuration.
Tooltip appearance (font, colors, border) can be customized via the theme. See the Tooltip Styling section.
Keyboard Navigation
Full keyboard support for accessible operation without a mouse:
| Arrow keys | Navigate between cells in the sheet. |
| Enter | Start editing the focused cell. Confirm edit. |
| Escape | Cancel editing. |
| Tab / Shift+Tab | Move to next / previous cell. |
| Delete | Delete selected tasks. |
| Ctrl+Z / Ctrl+Y | Undo / Redo. Ctrl+Shift+Z also redoes. |
| Ctrl++ / Ctrl+- | Zoom in / Zoom out. |
| Ctrl+C / Ctrl+X / Ctrl+V | Copy / Cut / Paste tasks. |
Filtering
Filter tasks dynamically using a predicate function. Parent tasks of matching tasks remain visible automatically.
// Filter by a condition
gantt.filter = (task) => task.getPropertyValue('department') === 'Engineering';
// Filter by date range
gantt.filter = (task) =>
task.startTime != null && task.startTime >= new Date('2027-02-01');
// Filter by assigned resource
gantt.filter = (task) => task.getResourceByResourceId('r1') != null;
// Clear filter
gantt.clearFilter();Built-in Filters
TaskFilters provides ready-made predicates for common queries:
import { TaskFilters } from '@timelinekit/core';
// Single built-in filter
gantt.filter = TaskFilters.criticalPath;
gantt.filter = TaskFilters.incomplete;
gantt.filter = TaskFilters.complete;
gantt.filter = TaskFilters.behindSchedule;
gantt.filter = TaskFilters.milestones;
// Parameterized filters
gantt.filter = TaskFilters.byName('Review');
gantt.filter = TaskFilters.byResource(dev);
gantt.filter = TaskFilters.byDateRange(new Date('2027-01-01'), new Date('2027-03-31'));
// Combine multiple filters (AND logic)
gantt.filter = TaskFilters.combine(
TaskFilters.incomplete,
TaskFilters.byResource(dev),
);Undo & Redo
All user actions (editing, drag & drop, adding/removing tasks) are recorded and can be undone/redone.
gantt.undo();
gantt.redo();
// Observe availability (e.g. to enable/disable toolbar buttons)
gantt.canUndo$.subscribe(canUndo => {
undoButton.disabled = !canUndo;
});
gantt.canRedo$.subscribe(canRedo => {
redoButton.disabled = !canRedo;
});Copy & Paste
Copy, cut, and paste tasks while preserving hierarchy and internal links.
// Copy / cut selected tasks
await gantt.copy();
await gantt.cut();
// Paste (returns info about pasted tasks)
const result = await gantt.paste();
if (result) {
console.log(result.tasks); // pasted tasks
console.log(result.links); // pasted internal links
console.log(result.droppedLinks); // links that couldn't be pasted
}Synchronizing Changes
Use change events to synchronize the chart state with a backend API or database. Events fire for every user interaction — editing cells, dragging tasks, creating links, etc.
// Track task changes (edits, drag & drop, scheduling updates)
gantt.events.taskChanged$.subscribe(({ task }) => {
api.updateTask(task.id, {
name: task.name,
startTime: task.startTime,
endTime: task.endTime,
progress: task.progress,
});
});
// Track new tasks
gantt.events.taskAdded$.subscribe(({ task }) => {
api.createTask({
id: task.id,
name: task.name,
startTime: task.startTime,
endTime: task.endTime,
});
});
// Track removed tasks
gantt.events.taskRemoved$.subscribe(({ task }) => {
api.deleteTask(task.id);
});
// Track dependency links
gantt.events.linkAdded$.subscribe(({ link }) => {
api.createLink({
id: link.id,
fromId: link.from.id,
toId: link.to.id,
type: link.type,
lag: link.lag,
});
});
gantt.events.linkRemoved$.subscribe(({ link }) => {
api.deleteLink(link.id);
});For bulk operations (initial load, import), use load() and save() to transfer the full state as JSON instead of reacting to individual events.