Data viz
Gantt
A planning surface, not just a picture. An editable task table is welded to a scrollable timeline of draggable bars — summary roll-ups, milestone diamonds, and finish-to-start dependency arrows you can draw and delete. Dates snap to whole days; every edit happens in place.
npx shadcn@latest add @orbit/ganttOverview
Live component — drag a bar along the timeline, pull its edges, click a name to rename, or drag a bar's end dot onto another row to link it. Click an arrow to remove the dependency, zoom the day columns, or hide table columns from the Columns menu.
Drag a bar, pull an edge, or draw a wire — callbacks land here.
Anatomy
Two halves, one grid: a fixed task table on the left and a horizontally-scrolling timeline on the right share the same 46px row height, so every task lines up with its bar no matter how far you scroll the dates. Weekends shade, months band the 58px header, and a primary rule marks today.
Interactions
Plan by direct manipulation — no dialogs. Dates snap to whole days as you drag; durations and names commit on Enter or blur.
Dependencies
An arrow runs from a predecessor's end into its successor's start. The arrows are live — they bend and follow as you drag either bar, so a slip downstream is obvious at a glance. Forward links elbow just before the successor; a link that has to run backwards routes along the row boundary, splitting cells instead of crossing bars — try dragging Retro writeup around.
Milestones
Reserve diamonds for dates whose slip changes the plan — sign-offs, launches, gates. They sit between phases, accept dependencies on both sides, and drag along the timeline like any bar.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| tasks / defaultTasks | GanttTask[] | — | Controlled / uncontrolled task rows, in display order. Tasks carry { id, name, kind?, color?, start, end, progress?, assignee?, dependencies? } — start/end are day indices from startDate (inclusive), dependencies list predecessor ids. |
| onTasksChange | (tasks) => void | — | Fires with the full next list on every edit — bar move/resize, rename, duration, start date, progress, dependency add/remove, and Add task. |
| onTaskMove | (id, start, end) => void | — | Fires when a bar drag/resize (or arrow-key move) commits, with the new day range. |
| onDependencyCreate | (dep: GanttDependency) => void | — | A wire was drawn: { from: predecessorId, to: successorId }. |
| onDependencyRemove | (dep: GanttDependency) => void | — | A wire (or table chip) was deleted. |
| onSelectTask | (task) => void | — | A row or bar was selected (click, Enter or Space). |
| startDate | Date | Jun 1 2026 | The date at day index 0. |
| totalDays | number | 63 | Timeline length in days. |
| today | Date | — | Draws the today rule when inside the timeline. Omit to hide; pass a fixed date for deterministic demos. |
| defaultDayWidth | number | 30 | Initial day-column width in px; the toolbar zoom steps it between 16 and 54. |
| title | ReactNode | — | Toolbar title, next to the auto-derived date range. |
| legend | GanttLegendItem[] | — | Footer phase swatches ({ label, color }). The footer — with the milestone key and interaction hint — renders only when set. |
| showToolbar / showAddTask | boolean | true | Hide the toolbar row / just its Add task button. |
| createTask | (tasks) => GanttTask | — | Factory for the Add task button — mint real ids here. Default appends a 5-day task after the last row. |
| editable | boolean | true | false renders read-only: no drag, resize, linking or cell editing. |
| …rest | HTMLAttributes | — | Forwarded to the root <div>, including ref and className. |
Usage
A Gantt earns its keep when work has real sequence and duration. For a simple list of dated items with no dependencies, a calendar or table is lighter.
Group work into phases
Summary rows give readers a scannable spine before they dive into individual tasks.
Track hundreds of rows here
Past ~40 rows a Gantt becomes a wall. Filter to a team or phase, or switch to a table.
Reserve milestones for decisions
Sign-offs, launches, gates — dates whose slip changes the plan. Not every deliverable.
Encode status in bar color
Color maps to phase here. Use the progress fill — or a status badge in the table — for state.
Keyboard & accessibility
Bars are focusable with an arrow-key alternative to drag, and each committed move is announced via a polite live region. Table edits are plain inputs — Enter commits, Escape cancels — and Escape also backs out of a drag, a wire, or an open popover. Rows carry table semantics; bars are labelled with their task, dates and percent complete.