A JavaScript library to create Gantt diagrams built on SVG
To add the ApexGantt to your project and its dependencies, install the package from npm.
npm install apexganttimport ApexGantt from 'apexgantt';To create a basic gantt with minimal configuration, write as follows:
<div id="gantt-container"></div>const ganttOptions = {
  series: [
    {
      id: 'a',
      startTime: '10-11-2024',
      endTime: '11-01-2024',
      name: 'task 1',
      progress: 65,
    },
    {
      id: '5',
      startTime: '10-11-2024',
      endTime: '10-26-2024',
      name: 'subtask 1.1',
      parentId: 'a',
      progress: 65,
    },
  ],
};
const gantt = new ApexGantt(document.getElementById('gantt-container'), ganttOptions);
gantt.render();The layout can be configured by either setting the properties in the table below by passing a second arg to ApexGantt with these properties set. The latter takes precedence.
| Options | Default | Description | 
|---|---|---|
| width | 100% | The width of graph container | 
| height | 500px | The height of graph container | 
| series, | [] | Data for gantt. See format below | 
| theme, | light | Built in light and dark theme for easy styling | 
| canvasStyle | None | The css styles for canvas root container | 
| viewMode | ViewMode.Month | View mode | 
| arrowColor | #0D6EFD | Color for the dependency arrows | 
| rowHeight | 28 | Height for timeline row | 
| rowBackgroundColors | ['#FFFFFF'] | Alternate row colors. | 
| barBackgroundColor | #537CFA | Background color for timeline bar | 
| barBorderRadius | 5px | Border radius for timeline bar | 
| barMargin | 4 | Top and bottom margin for timeline bar | 
| barTextColor | #FFFFFF | Text color for timeline bar | 
| cellBorderColor | #eff0f0 | Border color for all table cells and timeline cells | 
| cellBorderWidth | 1px | Border width for all table cells and timeline cells | 
| enableToolbar | false | Enable/disable graph toolbar | 
| enableResize | true | Enable/disable gantt sidebar resize | 
| enableExport | true | Enable/disable gantt export options | 
| enableTaskDrag | true | Enable/disable gantt export options | 
| enableTaskEdit | false | Enable/disable gantt export options | 
| enableTaskResize | true | Enable/disable gantt export options | 
| headerBackground | #f3f3f3 | Background color for header | 
| inputDateFormat | MM-DD-YYYY | Input date format | 
| tasksContainerWidth | 425 | Task sidebar container width | 
| tooltipId | apexgantt-tooltip-container | The tooltip HTML element id | 
| tooltipTemplate | tooltipTemplate | The HTML template for tooltip | 
| tooltipBorderColor | #BCBCBC | The border color of tooltip | 
| tooltipBGColor | #FFFFFF | The background color of tooltip | 
| fontSize | 14px | The size of font of nodes | 
| fontFamily | None | The font family of nodes | 
| fontWeight | 400 | The font weight of nodes | 
| fontColor | #000000 | The font color of nodes | 
| annotationBgColor | #F9D1FC | The backgrond color of annotation | 
| annotationBorderColor | #E273EA | The backgrond color of annotation | 
| annotationBorderDashArray | [] | The border dash array of annotation | 
| annotationBorderWidth | 2 | The border width of annotation | 
| annotationOrientation | Orientation.Horizontal | The orientation of annotation | 
| annotations | [] | See sample data below | 
Default tooltip template
tooltipTemplate(task, dateFormat) {
    const items = [
      `<div>
        <strong>Name:</strong>
        <span>${task.name}</span>
      </div>
      `,
    ];
    if (task.type === TaskType.Task) {
      items.push(`
        <div>
          <strong>Start:</strong>
          <span>${getTaskTextByColumn(task, ColumnKey.StartTime, dateFormat)}</span>
        </div>
        <div>
          <strong>End:</strong>
          <span>${getTaskTextByColumn(task, ColumnKey.EndTime, dateFormat)}</span>
        </div>
        <div>
          <strong>Duration:</strong>
          <span>${getTaskTextByColumn(task, ColumnKey.Duration, dateFormat)}</span>
        </div>
        <div>
          <strong>Progress:</strong>
          <span>${task.progress}%</span>
        </div>
      `);
    } else if (task.type === TaskType.Milestone) {
      items.push(`
        <div>
          <strong>Date:</strong>
          <span>${getTaskTextByColumn(task, ColumnKey.StartTime, dateFormat)}</span>
        </div>
      `);
    }
    if (task.dependency) {
      items.push(`
        <div>
          <strong>Dependency:</strong>
          <span>${task.dependency}</span>
        </div>
      `);
    }
    return `
      <div style='display:flex;flex-direction:column;align-items:left;gap:5px;padding:5px 10px;'>
        ${items.join('')}
      </div>
    `;
  },Each tasks should be in below format
[
  {
    id: 'a', // unique id of the task
    startTime: '10-11-2024', // start time of the task
    endTime: '11-01-2024', // end time of the task
    name: 'task 1', // task name
    parentId: 'a', // parent task id
    progress: 65, // progress in percentage
  },
];Each tasks should be in below format
[
  {
    x1: '10-25-2024', // start date
    x2: 'END_DATE', // optional. If present, draw a rect from x1 to x2. If null, only draw line on x1,
    label: {
      text: 'Annotation rect', // label for the annotation
      fontColor: '#333333', // optional
      fontFamily: 'Arial', // optional
      fontSize: '12px', // optional
      fontWeight: 'bold', // optional
    },
  },
];Map your existing data structure to ApexGantt format without manual transformation.
const apiData = [
  {
    task_id: 'T1',
    task_name: 'Design Phase',
    start_date: '01-01-2024',
    end_date: '01-15-2024',
    completion: 75,
  },
];
const gantt = new ApexGantt(document.getElementById('gantt'), {
  series: apiData,
  parsing: {
    id: 'task_id',
    name: 'task_name',
    startTime: 'start_date',
    endTime: 'end_date',
    progress: 'completion',
  },
});Use dot notation for nested properties and inline transforms for data conversion:
const nestedData = [
  {
    project: {
      task: {id: 'T1', title: 'Design'},
      dates: {start: '01-01-2024', end: '01-15-2024'},
      status: {completion: 0.75},
    },
  },
];
const gantt = new ApexGantt(document.getElementById('gantt'), {
  series: nestedData,
  parsing: {
    id: 'project.task.id',
    name: 'project.task.title',
    startTime: 'project.dates.start',
    endTime: 'project.dates.end',
    progress: {
      key: 'project.status.completion',
      transform: (value) => value * 100, // convert to percentage
    },
  },
});Supported fields: id, name, startTime, endTime, progress, type, parentId, dependency, barBackgroundColor, rowBackgroundColor, collapsed
Updates the entire Gantt chart with new configuration and task data.
| Name | Type | Description | 
|---|---|---|
| options | Object | Contains updated config and data. Must include a tasksarray and other Gantt configuration options. | 
ganttInstance.update({
  series: [
    {
      id: 'task-1',
      name: 'Design Phase',
      start: '2025-07-01',
      end: '2025-07-10',
      progress: 40,
    },
    // more tasks...
  ],
  viewMode: 'Week',
});Updates the specific task with provided task data.
| Name | Type | Description | 
|---|---|---|
| taskId | string | ID of the task to be updated | 
| taskData | Object | Data of the task to be updated | 
ganttInstance.updateTask('task-1', {
  name: 'Design Phase',
  start: '2025-07-01',
  end: '2025-07-10',
  progress: 40,
});Zooms in the gantt based on current view mode. View mode direction for zoom in year -> quarter -> month -> week -> day
ganttInstance.zoomOut();Zooms out the gantt based on current view mode. View mode direction for zoom in day -> week -> month -> quarter -> year
ganttInstance.zoomOut();ApexGantt emits CustomEvents on the container element when tasks are updated through the dialog form.
| Event | When | Detail | 
|---|---|---|
| taskUpdate | Task is being updated | { taskId, updates, updatedTask, timestamp } | 
| taskUpdateSuccess | Update completed successfully | { taskId, updatedTask, timestamp } | 
| taskValidationError | Form validation failed | { taskId, errors, timestamp } | 
| taskUpdateError | Update failed | { taskId, error, timestamp } | 
import ApexGantt, {GanttEvents} from 'apexgantt';
const container = document.getElementById('gantt');
const chart = new ApexGantt(container, {series: tasks});
chart.render();
// Hook into updates to save to your backend
container.addEventListener(GanttEvents.TASK_UPDATE_SUCCESS, async (e) => {
  const {updatedTask} = e.detail;
  /* use this updatedTask for any server operations */
});
// handle any errors
container.addEventListener(GanttEvents.TASK_UPDATE_ERROR, (e) => {
  console.error('Update failed:', e.detail.error);
});import {useRef, useEffect} from 'react';
import ApexGantt, {GanttEvents} from 'apexgantt';
function GanttChart({tasks}) {
  const containerRef = useRef(null);
  useEffect(() => {
    const chart = new ApexGantt(containerRef.current, {series: tasks});
    chart.render();
    const handleSuccess = async (e) => {
      const {updatedTask} = e.detail;
      /* use this updatedTask for any server operations */
    };
    containerRef.current.addEventListener(GanttEvents.TASK_UPDATE_SUCCESS, handleSuccess);
    return () => {
      containerRef.current?.removeEventListener(GanttEvents.TASK_UPDATE_SUCCESS, handleSuccess);
      chart.destroy();
    };
  }, [tasks]);
  return <div ref={containerRef} />;
}