Custom Task-List Columns

The task-list panel on the left side of the chart shows a configurable set of columns. Pass columnConfig to control which columns appear, in what order, and how wide they are. You can also add fully custom columns with a render function.

Built-in columns

ColumnKeykey stringDefault shownDescription
Name'name'YesTask name
StartTime'startTime'YesStart date
EndTime'endTime'YesEnd date
Duration'duration'NoComputed working-day duration
Progress'progress'NoCompletion percent as text
ProgressRing'progressRing'NoCircular progress indicator
Wbs'wbs'NoWork Breakdown Structure code

Showing a subset of columns

const gantt = new ApexGantt(document.getElementById('chart'), {
  series: tasks,
  columnConfig: [
    { key: 'name',      title: 'Task',     minWidth: '200px', flexGrow: 3 },
    { key: 'startTime', title: 'Start',    minWidth: '100px', flexGrow: 1 },
    { key: 'endTime',   title: 'End',      minWidth: '100px', flexGrow: 1 },
    { key: 'progress',  title: 'Progress', minWidth: '80px',  flexGrow: 1 },
  ],
})

ColumnListItem properties

PropertyTypeDescription
keyColumnKey | stringBuilt-in key or any string for a custom column
titlestringColumn header text
minWidthstringCSS minimum width (e.g. '120px')
flexGrownumberFlex grow ratio; controls how extra space is distributed
visiblebooleanWhen false, the column is hidden
renderColumnRendererCustom cell renderer (required for custom columns)
accessor(task) => unknownExtracts the cell's underlying value — used by SVG export

Adding WBS and duration

columnConfig: [
  { key: 'wbs',       title: '#',        minWidth: '50px',  flexGrow: 0 },
  { key: 'name',      title: 'Task',     minWidth: '180px', flexGrow: 3 },
  { key: 'duration',  title: 'Days',     minWidth: '60px',  flexGrow: 0 },
  { key: 'startTime', title: 'Start',    minWidth: '100px', flexGrow: 1 },
  { key: 'endTime',   title: 'End',      minWidth: '100px', flexGrow: 1 },
  { key: 'progressRing', title: '',      minWidth: '40px',  flexGrow: 0 },
],

Custom column with a render function

The render function receives (ctx, el) where ctx is the render context and el is the pre-attached cell DOM element.

Return a string to have the library set it as innerHTML. Return void after mounting your own content into el. Return a cleanup function to unmount framework components when the cell is discarded.

const gantt = new ApexGantt(el, {
  series: tasks,
  columnConfig: [
    { key: 'name',     title: 'Task',   minWidth: '180px', flexGrow: 3 },
    { key: 'startTime',title: 'Start',  minWidth: '100px', flexGrow: 1 },
    {
      key: 'status',
      title: 'Status',
      minWidth: '100px',
      flexGrow: 1,
      render: (ctx) => {
        const { task } = ctx
        const label =
          task.progress === 100 ? 'Done' :
          task.progress > 0    ? 'In Progress' :
                                 'Not Started'
        const color =
          task.progress === 100 ? '#10B981' :
          task.progress > 0    ? '#F59E0B' :
                                 '#94A3B8'
        return `
          <span style="
            display:inline-block;padding:2px 8px;border-radius:10px;
            background:${color}22;color:${color};font-size:11px;font-weight:600;
          ">${label}</span>
        `
      },
      accessor: (task) => task.progress,
    },
  ],
})

Built-in avatars renderer

When tasks include an assignees array, use the built-in renderers.avatars factory to render stacked avatar chips without writing the DOM yourself:

import ApexGantt, { renderers } from 'apexgantt'

const gantt = new ApexGantt(el, {
  series: [
    {
      id: 'task-1',
      name: 'Design System',
      startTime: '2024-03-01',
      endTime: '2024-03-15',
      progress: 60,
      assignees: [
        { name: 'Alice Chen',  avatarUrl: '/avatars/alice.jpg' },
        { name: 'Bob Patel',   color: '#6366F1' },
        { name: 'Carol Smith', initials: 'CS', color: '#10B981' },
      ],
    },
  ],
  columnConfig: [
    { key: 'name',     title: 'Task',     minWidth: '180px', flexGrow: 3 },
    { key: 'startTime',title: 'Start',    minWidth: '100px', flexGrow: 1 },
    {
      key: 'assigned',
      title: 'Assigned',
      minWidth: '120px',
      flexGrow: 1,
      render: renderers.avatars({
        accessor: (task) => task.assignees,
        max: 3,         // show up to 3 avatars, then "+N"
        size: 24,       // diameter in px
        overlap: 8,     // how much each avatar overlaps the previous
      }),
    },
  ],
})

AvatarsRendererOptions

OptionTypeDefaultDescription
accessor(task) => Assignee[]RequiredReturns the list of assignees for a task
maxnumber4Max avatars shown; excess shown as +N
sizenumber24Avatar diameter in pixels
overlapnumber8Overlap between adjacent avatars in pixels
borderColorstring'#FFFFFF'Border around each avatar
fallbackColorstringBackground for initials fallback when Assignee.color is not set

Assignee fields

FieldTypeDescription
namestringDisplay name; used for alt text and initials source
avatarUrlstringImage URL — when set, renders an <img>
initialsstringOverride for the two-letter initials fallback
colorstringBackground color for the initials fallback

React example

import { ApexGanttChart } from 'react-apexgantt'
import { renderers } from 'apexgantt'
import type { GanttUserOptions } from 'react-apexgantt'

const options: Omit<GanttUserOptions, 'series'> = {
  columnConfig: [
    { key: 'name',     title: 'Task',     minWidth: '180px', flexGrow: 3 },
    { key: 'startTime',title: 'Start',    minWidth: '100px', flexGrow: 1 },
    { key: 'endTime',  title: 'End',      minWidth: '100px', flexGrow: 1 },
    {
      key: 'status',
      title: 'Status',
      minWidth: '90px',
      flexGrow: 1,
      render: (ctx) => {
        const pct = ctx.task.progress
        const label = pct === 100 ? 'Done' : pct > 0 ? 'In Progress' : 'Not Started'
        const color = pct === 100 ? '#10B981' : pct > 0 ? '#F59E0B' : '#94A3B8'
        return `<span style="color:${color};font-size:11px;font-weight:600">${label}</span>`
      },
    },
    {
      key: 'assigned',
      title: 'Team',
      minWidth: '110px',
      flexGrow: 1,
      render: renderers.avatars({ accessor: (task) => task.assignees }),
    },
  ],
}

export default function CustomColumnsGantt() {
  return <ApexGanttChart tasks={tasks} options={options} height="500px" />
}

Vue example

<template>
  <ApexGanttChart :tasks="tasks" :options="ganttOptions" height="500px" />
</template>

<script setup lang="ts">
import { renderers } from 'apexgantt'
import type { GanttUserOptions } from 'vue-apexgantt'

const ganttOptions: Partial<GanttUserOptions> = {
  columnConfig: [
    { key: 'name',     title: 'Task',    minWidth: '180px', flexGrow: 3 },
    { key: 'startTime',title: 'Start',   minWidth: '100px', flexGrow: 1 },
    { key: 'endTime',  title: 'End',     minWidth: '100px', flexGrow: 1 },
    { key: 'progress', title: 'Progress',minWidth: '80px',  flexGrow: 1 },
    {
      key: 'assigned',
      title: 'Team',
      minWidth: '110px',
      flexGrow: 1,
      render: renderers.avatars({ accessor: (task) => task.assignees, max: 3 }),
    },
  ],
}
</script>