Appearance
Task Gantt
TaskGantt is a separate component for project tasks. Resource Timeline remains responsible for resources, assignments and lazy entry loading.
Data contract
All dates are civil YYYY-MM-DD dates, with exclusive interval ends. A task from September 9 through September 12 uses { start: '2026-09-09', end: '2026-09-13' }. There are no times, time zones, working-day exclusions or implicit duration units.
| Field | Meaning |
|---|---|
id, title | Required, nonempty strings; IDs are unique in the collection |
kind: 'task' | Activity with optional schedule: { start, end } and progress from 0 to 100 |
kind: 'summary' | Parent row; bounds and progress are derived from descendants |
kind: 'milestone' | Point at required date; movable but not resizable |
parentId | Optional reference to a summary in the same collection |
Activities without a schedule remain visible in the sidebar, without a bar. Sibling order follows the input array. Summaries may be nested; their bounds include scheduled descendants and milestones. Summary progress is the arithmetic mean of descendant activities, with omitted progress counted as zero. Milestones do not contribute to progress. Summaries cannot be dragged or resized.
TaskGanttData contains tasks and optional dependencies. Each dependency has predecessorId, successorId and type: 'finish-to-start'. Endpoints must be activities or milestones. Missing references, duplicate links, self-links, cyclic dependencies, cyclic parents, invalid progress and invalid intervals throw before replacing confirmed data. Inputs are copied and frozen.
Dependencies draw SVG arrows between visible scheduled tasks. Connected arrows follow the bar during movement/resizing and reset with a cancelled preview. When the vertical connection lies over a lower target bar, it enters its top edge; otherwise it approaches from the left. They do not calculate or constrain dates, shift successors, or prevent overlapping task intervals. Collapsed descendants hide their arrows. The full task/dependency collection is required; rows are virtualized, but lazy task loading is not implemented.
Vanilla JavaScript
ts
import { createTaskGantt, type TaskGanttData } from '@xsigns/chronosketch/task-gantt'
import '@xsigns/chronosketch/styles.css'
import '@xsigns/chronosketch/task-gantt/styles.css'
let data: TaskGanttData = {
tasks: [
{ id: 'project', kind: 'summary', title: 'Website launch' },
{ id: 'design', kind: 'task', parentId: 'project', title: 'Design',
schedule: { start: '2026-09-09', end: '2026-09-13' }, progress: 57 },
{ id: 'launch', kind: 'milestone', parentId: 'project', title: 'Release',
date: '2026-09-15' },
],
dependencies: [
{ predecessorId: 'design', successorId: 'launch', type: 'finish-to-start' },
],
}
const gantt = createTaskGantt({
data,
range: { start: '2026-09-01', days: 90 },
locale: 'en-US',
title: 'Website launch',
onTaskDateChangeRequested({ task }) {
data = { ...data, tasks: data.tasks.map(item => item.id === task.id ? task : item) }
gantt.setData(data)
},
})
gantt.mount(document.querySelector<HTMLElement>('#tasks')!)
// On teardown: gantt.destroy()The example confirms moves locally. In an application, validate and persist the proposed data first, then supply the canonical result through setData. Handle save errors and concurrent requests in the application. Requests do not mutate confirmed library data, and the temporary drag preview ends when the gesture ends.
Options and lifecycle
Required options are data and range: { start, days }; the horizon is independent of the last task. days must be a positive safe integer. The exclusive end is computed using civil calendar-day arithmetic. Existing { start, end } ranges remain accepted as deprecated compatibility input; supplying both days and end fails. Optional date sets initial scroll position (default: horizon start). The Today button scrolls within that horizon; it does not extend the range.
Optional title defaults to Task Manager. locale defaults to de-DE; German and English controls are provided. controlsStyle and component dimensions use shared sizing and styles. zoom defaults to 1 and accepts 1, 2, 4, 6 or 8 days per fixed-width column. showZoom: false hides the slider. Changing zoom keeps the horizon start anchored at the left edge; after scrolling right, it preserves the time at the viewport center. Editing still snaps to individual civil days. Month, ISO week and day headers remain visible.
taskPresentation(task) may return color, icon and image: { src, variant?: 'avatar' | 'logo' }. Media is decorative, using the shared media contract. Keep application metadata in your own lookup keyed by task ID.
Instance methods: mount(host), destroy(), setData(data), setZoom(value), setOptions(options), getSnapshot() and subscribe(listener) (returns disposal). The snapshot contains confirmed data and projected rows, including depth, expanded state, schedule and progress. Subscriptions report data/collapse changes, not zoom changes. setData retains collapsed groups and scroll position. setOptions replaces the full configuration and remounts the view, resetting its scroll position; supply current data and all desired options. Invalid data/options leave the previous view intact. Imports and construction do not require a DOM; mounting requires a browser.
Consumer-owned dialogs
The library does not mount a form or accept framework components in its domain contract. Provide any combination of these callbacks:
onTaskCreateRequested(request): Add task requests a new root task; a summary's plus control suppliesparentId. The type permits a suggestedschedule, but the current buttons do not supply one. Your application assigns IDs.onTaskEditRequested(task): Activate a task name or bar to open your editor.onTaskDateChangeRequested({ previous, task, action }): proposed move orresize-start/resize-endoperation; both task versions are provided.
Each callback returns void; returned promises or objects are not used as data. Open your React, Vue, Vanilla or application dialog, await its result, then update data through the adapter or setData. Cancellation needs no library action. Removing a callback removes its corresponding creation/editing capability.
Bars support pointer dragging and keyboard movement with Alt + Left/Right. Resize handles support Left/Right. Escape cancels a pointer gesture. Scrolling, window blur, replacing data and teardown also cancel active gestures and dispose listeners. Resize cannot create an empty or negative interval. Enter activates editing when an edit callback is provided.
React
tsx
import { TaskGantt } from '@xsigns/chronosketch/react'
import type { TaskGanttOptions } from '@xsigns/chronosketch/task-gantt'
export function ProjectTasks({ options }: { options: TaskGanttOptions }) {
return <TaskGantt {...options} />
}Import the two stylesheets from the Vanilla example. Keep confirmed data in React state and pass updated data after your dialog/save completes. Callback changes use the latest function. Normal data changes preserve the mounted instance; configuration changes (range start/days, locale, title, dimensions, controls or callback availability) rebuild it. zoom synchronizes in place.
Vue 3
vue
<script setup lang="ts">
import { TaskGantt } from '@xsigns/chronosketch/vue'
import type { TaskGanttOptions } from '@xsigns/chronosketch/task-gantt'
defineProps<{ options: TaskGanttOptions }>()
</script>
<template><TaskGantt :options="options" /></template>Import the same two stylesheets. Replace confirmed options.data after your application dialog/save completes. Lifecycle and configuration behavior match the React adapter; unmount disposes the shared renderer and its subscriptions.
Current limits
This first version has no automatic scheduling, working calendars, constraints, critical path, dependency editor, other dependency types, drag reparenting, resource assignments, hourly view, custom content templates or native chart renderer. The demo's form is sample application code, not an exported package dialog.
Optional progress editing
Set editableProgress: true and provide onTaskProgressChangeRequested to show an independent progress slider vertically centered in scheduled activity bars. The option defaults to false; without a handler the control remains hidden. Summaries and milestones have no progress editor. Unscheduled activities can be edited in your application's dialog.
ts
const gantt = createTaskGantt({
data,
range: { start: '2026-09-01', days: 90 },
editableProgress: true,
onTaskProgressChangeRequested({ previous, task }) {
// Validate/persist task in your application, then supply confirmed data.
data = { ...data, tasks: data.tasks.map(item => item.id === previous.id ? task : item) }
gantt.setData(data)
},
})TaskProgressChange contains previous and proposed task, both activities. Progress is clamped to 0–100 in whole percentage steps. Dragging previews the fill and a temporary percentage inside the bar. Ancestor summary fills update live using the same aggregation as confirmed data, including collapsed descendants. Cancellation restores all previewed fills; releasing requests confirmation. Dates and dependencies stay unchanged. The component retains confirmed data until the consumer supplies an update; summary progress then recalculates. No-op gestures emit no request. Escape, scrolling, blur and data replacement cancel active pointer previews. The focused slider supports native range keyboard controls, including arrow keys and Home/End. Each keyboard change requests confirmation.
Vanilla uses setOptions for enabling/disabling; React accepts the two options as props and Vue accepts them through options. Capability changes rebuild the view, while confirmed data updates preserve the mounted instance. The demo includes a German/English progress-editing switch; this demo-only switch resets on reload.
Progress grips appear on task hover or slider focus; touch devices without hover keep them visible. Summaries show their aggregate percentage within the visible part of the bar, including during horizontal scrolling. Both the fill and number follow live progress previews and restore on cancellation.
The demo task form uses ChronoSketch's shared Material date picker for start, exclusive end and milestone dates, including German/English formatting and keyboard date navigation. Optional fields can be cleared for unscheduled activities. This form and its field adapter remain demo code; there is no standalone public DatePicker export in this version.
Native TaskManagerView and TaskTimelineView also accept a code-configured title with the same default; see the Swift guide.
The optional title option sets the header independently of task titles, for example title: 'Website launch'. Omitting it displays Task Manager. Multiple root summaries are supported; each row title comes from its task's title.
In the demo, creation offers task, summary task and milestone types. Choose a summary as parent or leave the item at the top level. The plus action on a summary prefills that parent. Editing permits changing the parent, excluding the item itself and its descendants. An existing item's type remains fixed; create a summary when it should contain children. These controls belong to the consumer form, and all three integrations receive the same task data contract.
Optional row reordering
Supply onTaskOrderChangeRequested to enable the sidebar grip. Drag it onto the upper/lower half of another sibling's label to insert before/after, or focus the grip and press ArrowUp/ArrowDown. Summary descendants follow their summary, including collapsed descendants. Reordering never changes parent IDs, dates, progress or dependency links. Cross-parent drops are ignored.
ts
onTaskOrderChangeRequested(change) {
data = { ...data, tasks: change.tasks }
gantt.setData(data)
}TaskOrderChange contains taskId, targetId, position (before/after), and the proposed full tasks array. Confirm via setData in Vanilla or updated React data/Vue options. Omit the callback to disable. No-op drops emit no request. A floating copy of the sidebar cell follows the pointer while its source is dimmed. An insertion line previews valid placement; invalid targets show a localized “Cannot drop here” badge. Rows make room with a short animation, including time bars and connection paths. Invalid targets and cancellation restore the original order; confirmed data is unchanged during preview. Escape, pointer cancellation, scroll, blur, zoom, data updates and disposal cancel active gestures. Dragging supports pointer devices and touch grips; edge auto-scroll is not implemented. Scroll first, then drag, or use the keyboard.
Dependency connections adapt to vertical row previews as well as date movement. For an upper target, routing can leave the source top or enter the target bottom; otherwise the connecting bend points toward the target. This is local orthogonal routing, without global obstacle avoidance.
Native entry slice
The Swift Task Manager guide covers the first native hierarchy list with consumer date/duration/progress actions. A native chart with finish-to-start arrows, 1/2/4/6/8-day zoom, finite navigation and decorative media is also available. List and chart actions request the same consumer forms; native ordering uses a consumer action/form. The native chart also shows pinned month, ISO-week and day/zoom headers. Web interaction contracts above are unchanged.
Task zoom keeps the horizon start anchored when the viewport is at its left edge (including when the entire horizon fits). Zooming back in therefore keeps early tasks in view. After scrolling right, zoom retains the viewport center as before. This rule applies to native and Web TaskGantt; it does not reposition task dates or guarantee that every task fits at the most detailed zoom.
Native creation callbacks and consumer forms now support activities, milestones and summaries. Web creation behavior is unchanged.
Height modes
Use heightMode: 'fill' | 'content' (default 'fill') with the existing size options. For example, { heightMode: 'content', maxHeight: 600 } grows to the visible rows until the height limit; overflow scrolls internally. Grid lines end at the final row in both modes. setHeightMode() resets to fill without remounting; React/Vue synchronize the option in place. Full setOptions retains its existing replacement behavior. See the shared resource/task height contract for height/min/max precedence, empty space and scrollbar behavior.
Horizontal overflow exposes the same visible, draggable and keyboard-operable scrollbar as resource Gantt. It remains below the visible viewport in fill/content modes. See scrollbar styling.