# Gantt URL: /docs/web/components/gantt A Gantt chart component with drag-and-drop task scheduling, timeline zoom, custom markers, and sidebar navigation. **Demo:** ```tsx 'use client'; import { useCallback, useState } from 'react'; import { type GanttFeature, type GanttStatus, type Range, GanttProvider, GanttSidebar, GanttSidebarGroup, GanttSidebarItem, GanttTimeline, GanttHeader, GanttToday, GanttFeatureList, GanttFeatureListGroup, GanttFeatureRow } from '@docyrus/ui/components/gantt'; import { addDays } from 'date-fns'; import { PropControls, type PropControl } from '@/components/prop-controls'; // ─── Statuses ───────────────────────────────────────────────────────────────── const STATUSES = { planned: { id: 'planned', name: 'Planned', color: '#6b7280' }, 'in-progress': { id: 'in-progress', name: 'In Progress', color: '#3b82f6' }, review: { id: 'review', name: 'Review', color: '#a855f7' }, done: { id: 'done', name: 'Done', color: '#22c55e' } } satisfies Record; // ─── Initial Features ───────────────────────────────────────────────────────── const today = new Date(); const INITIAL_FEATURES: GanttFeature[] = [ { id: 'f1', name: 'Design system audit', startAt: addDays(today, -10), endAt: addDays(today, -3), status: STATUSES.done }, { id: 'f2', name: 'Component library setup', startAt: addDays(today, -5), endAt: addDays(today, 2), status: STATUSES['in-progress'] }, { id: 'f3', name: 'Authentication flow', startAt: addDays(today, 1), endAt: addDays(today, 12), status: STATUSES['in-progress'] }, { id: 'f4', name: 'Dashboard layout', startAt: addDays(today, 5), endAt: addDays(today, 15), status: STATUSES.planned }, { id: 'f5', name: 'API integration', startAt: addDays(today, 8), endAt: addDays(today, 22), status: STATUSES.planned }, { id: 'f6', name: 'Code review and QA', startAt: addDays(today, 18), endAt: addDays(today, 25), status: STATUSES.review }, { id: 'f7', name: 'Performance optimization', startAt: addDays(today, 20), endAt: addDays(today, 28), status: STATUSES.planned }, { id: 'f8', name: 'User testing', startAt: addDays(today, 26), endAt: addDays(today, 32), status: STATUSES.planned } ]; // ─── Group Helper ───────────────────────────────────────────────────────────── type FeatureGroup = { name: string; features: GanttFeature[]; }; function groupFeatures(features: GanttFeature[]): FeatureGroup[] { const groups: Record = {}; for (const feature of features) { const statusName = feature.status.name; const group = groups[statusName]; if (!group) { groups[statusName] = [feature]; } else { group.push(feature); } } return Object.entries(groups).map(([name, items]) => ({ name, features: items })); } // ─── GanttDemo ──────────────────────────────────────────────────────────────── export function GanttDemo() { const [features, setFeatures] = useState ))} ))} ))} ); } ``` ## Installation ```bash pnpm dlx @docyrus/cli add @docyrus/ui-gantt ``` **Dependencies:** - [@dnd-kit/core](https://www.npmjs.com/package/@dnd-kit/core) - [@dnd-kit/modifiers](https://www.npmjs.com/package/@dnd-kit/modifiers) - [date-fns](https://www.npmjs.com/package/date-fns) - [lodash](https://www.npmjs.com/package/lodash) - [lucide-react](https://www.npmjs.com/package/lucide-react) ## Usage ```tsx import { GanttProvider, GanttSidebar, GanttSidebarHeader, GanttSidebarGroup, GanttSidebarItem, GanttHeader, GanttContentHeader, GanttTimeline, GanttFeatureList, GanttFeatureListGroup, GanttFeatureRow, GanttFeatureItem, GanttFeatureItemCard, GanttFeatureDragHelper, GanttColumns, GanttColumn, GanttAddFeatureHelper, GanttToday, GanttMarker, GanttCreateMarkerTrigger } from '@docyrus/ui/components/gantt'; import type { GanttFeature, GanttStatus, Range } from '@docyrus/ui/components/gantt'; const statuses: GanttStatus[] = [ { id: 'todo', name: 'To Do', color: '#3b82f6' }, { id: 'in-progress', name: 'In Progress', color: '#f59e0b' }, { id: 'done', name: 'Done', color: '#22c55e' } ]; const features: GanttFeature[] = [ { id: '1', name: 'Design system', startAt: new Date(2025, 0, 1), endAt: new Date(2025, 0, 15), status: statuses[0] } ];
))}
``` ## Components | Component | Description | |-----------|-------------| | `GanttProvider` | Root context provider. Manages zoom, range, scroll, and drag state. | | `GanttSidebar` | Left sidebar container for task list navigation. | | `GanttSidebarHeader` | Sidebar header area. | | `GanttSidebarGroup` | Named group within the sidebar. | | `GanttSidebarItem` | Single task row in the sidebar. | | `GanttHeader` | Top header container area. | | `GanttContentHeader` | Timeline column headers (year/month/day labels based on range). | | `GanttTimeline` | Scrollable timeline area with DnD support. | | `GanttFeatureList` | Container for feature rows. | | `GanttFeatureListGroup` | Group within the feature list. | | `GanttFeatureRow` | Row container for a single feature. | | `GanttFeatureItem` | Draggable feature bar within a row. | | `GanttFeatureItemCard` | Visual card for the feature (colored by status). | | `GanttFeatureDragHelper` | Drag preview overlay during drag operations. | | `GanttColumns` | Background column grid for the timeline. | | `GanttColumn` | Single column in the grid. | | `GanttAddFeatureHelper` | Quick-add button that appears on column hover. | | `GanttToday` | Today marker line on the timeline. | | `GanttMarker` | Custom timeline marker (milestones, deadlines). | | `GanttCreateMarkerTrigger` | Button to create a new marker at a date. | ## API Reference ### GanttProvider | Prop | Type | Default | Description | |------|------|---------|-------------| | `zoom` | `number` | — | Zoom level controlling column density. | | `range` | `Range` | — | Timeline granularity (`'daily'`, `'monthly'`, `'quarterly'`). | | `columnWidth` | `number` | — | Pixel width per column. | | `sidebarWidth` | `number` | — | Sidebar width in pixels. | | `headerHeight` | `number` | — | Header height in pixels. | | `rowHeight` | `number` | — | Row height in pixels. | | `onAddItem` | `(date: Date) => void` | — | Called when quick-add is triggered. | | `placeholderLength` | `number` | — | Default duration for new tasks. | | `timelineData` | `TimelineData` | — | Date structure for timeline columns. | ### GanttSidebarGroup | Prop | Type | Default | Description | |------|------|---------|-------------| | `name` | `string` | — | Group label displayed in the sidebar. | | `className` | `string` | — | Additional CSS classes. | ### GanttSidebarItem | Prop | Type | Default | Description | |------|------|---------|-------------| | `feature` | `GanttFeature` | — | Task data to display. | | `className` | `string` | — | Additional CSS classes. | ### GanttFeatureItem | Prop | Type | Default | Description | |------|------|---------|-------------| | `feature` | `GanttFeature` | — | Task data for positioning and drag. | | `selected` | `boolean` | — | Highlight state. | | `onSelect` | `(feature: GanttFeature) => void` | — | Selection callback. | | `onDragEnd` | `(feature: GanttFeature, delta: Date) => void` | — | Called after drag with new date. | ### GanttFeatureItemCard | Prop | Type | Default | Description | |------|------|---------|-------------| | `feature` | `GanttFeature` | — | Task data (status color, name). | | `className` | `string` | — | Additional CSS classes. | ### GanttMarker | Prop | Type | Default | Description | |------|------|---------|-------------| | `id` | `string` | — | Unique marker identifier. | | `date` | `Date` | — | Marker position on the timeline. | | `label` | `string` | — | Marker label text. | | `className` | `string` | — | Additional CSS classes. | ## Type Reference ### GanttFeature | Field | Type | Description | |-------|------|-------------| | `id` | `string` | Unique identifier. | | `name` | `string` | Task name. | | `startAt` | `Date` | Task start date. | | `endAt` | `Date` | Task end date. | | `status` | `GanttStatus` | Current status with color. | | `lane` | `string` | Optional lane/swimlane identifier. | ### GanttStatus | Field | Type | Description | |-------|------|-------------| | `id` | `string` | Unique identifier. | | `name` | `string` | Display name. | | `color` | `string` | Hex color for the status. | ### Range `'daily'` | `'monthly'` | `'quarterly'` ### TimelineData ```tsx type TimelineData = Array<{ year: number; quarters: Array<{ months: Array<{ days: number }>; }>; }>; ```