Wondering what’s next for npm?Check out our public roadmap! »

    TypeScript icon, indicating that this package has built-in type declarations

    0.3.13 • Public • Published


    Npm Build Status Codecov License

    Simple library for creating gantt chart combined with task grid.

    Current features

    • highly customizable
    • contains two resizable parts: task grid and Gantt chart
    • resizable grid columns
    • tree-like structure with expandable and selectable rows
    • support for tasks with two date pairs (planned and actual)
    • single or multiple row selection mode
    • localization support
      • three out-of-box supported languages: English, Ukrainian, Russian
      • custom locales support
      • instant locale switching
    • configurable chart
      • four available chart scales: day, week, month, year
      • three available chart display modes: planned dates, actual dates, both
      • instant chart scale and display mode switching
    • written completely in Typescript
    • light codebase: only one dependency (lightweight Day.js is used to work with dates)

    Getting started

    Install and initialize

    With npm

    npm install ts-gantt
    import { TsGantt } from "ts-gantt";
    const chart = new TsGantt("#container-selector");

    include stylesheet ('ts-gantt/dist/styles.min.css') in any suitable way

    Or using CDN

    <link rel="stylesheet" href="https://unpkg.com/ts-gantt/dist/styles.min.css">
    <script src="https://unpkg.com/ts-gantt/dist/ts-gantt.umd.min.js"></script>
    const chart = new tsGantt.TsGantt("#container-selector");

    ⚠️for chart to function properly its container element must have relative, absolute or fixed position!

    Set your task list

    your tasks must implement following interface

    interface TsGanttTaskModel {
      id: string; // to avoid incorrect behaviour please use unique ids within array
      parentId: string | null | undefined; // use if you need tree-like structure
      name: string;  
      progress: number; // percentage from 0 to 100. higher or lower values will be truncated
      datePlannedStart: Date | null | undefined;
      datePlannedEnd: Date | null | undefined;  
      dateActualStart: Date | null | undefined;
      dateActualEnd: Date | null | undefined;
      localizedNames: {[key: string]: string} | null | undefined; // eg {"en": "Name", "uk": "Ім'я", "ru": "Имя"}

    to pass your task array to chart use 'tasks' property setter

    chart.tasks = yourTaskArray;

    task are updated in the same way. you should just pass actual task array when any change happens. change detection will find tasks that have been changed/added/removed and will replace/add/remove them in chart.

    Switch modes


    you can instantly switch chart language

    chart.locale = locale; // "en" | "uk" | "ru" or any custom locale you provided in chart options

    Timeline scale

    you can instantly switch chart timeline scale

    chart.chartScale = scale; // "day" | "week" | "month" | "year"

    Display mode (chart bars)

    you can instantly switch chart bar display mode

    chart.chartDisplayMode = mode; // "planned" | "actual" | "both"

    "planned" - show only planned dates bar on timeline
    "actual" - show only actual dates bar on timeline

    Select tasks

    select task rows programmatically

    chart.selectedTasks = [{id: "taskIdString"}];

    get selected tasks

    const selectedTasks = chart.selectedTasks;

    Customize chart

    you can customize chart in two ways:

    • edit or override styles in styles.css file
    • provide custom options to 'TsGantt' class constructor


    preffered way to customize styling is to change css variable values

    :root {
      --tsg-table-min-width: 100px;
      --tsg-chart-min-width: 100px;
      --tsg-nesting-indent: 20px; /* indent width per nesting level */
      --tsg-background-color: white;
      --tsg-foreground-color: black;
      --tsg-separator-color: rgb(80, 80, 80); /* color of movable vertical line between parts */
      --tsg-header-color: rgb(210, 210, 210); /* header background color */
      --tsg-border-color: rgb(190, 190, 190);
      --tsg-symbol-color: rgb(80, 80, 80); /* color of row special symbols */
      --tsg-selection-color: rgb(230, 230, 230); /* background color of selected row */
      --tsg-not-started-fg-color: dimgray; /* color of task row text depending on task state */
      --tsg-in-progress-fg-color: black;
      --tsg-overdue-fg-color: darkred;
      --tsg-completed-fg-color: darkgreen;
      --tsg-completed-late-fg-color: sienna;
      --tsg-today-line-color: orangered; /* color of vertical line on chart that represents today */  
      --tsg-chart-bar-color-1: skyblue; /* chart bars colors */
      --tsg-chart-bar-color-2: lightcoral;
      --tsg-chart-bar-accent-1: darkcyan;
      --tsg-chart-bar-accent-2: darkred;  
      --tsg-font-family: 'Calibri', sans-serif;
      --tsg-font-size: 14px;
      --tsg-line-height: 16px;
      --tsg-max-cell-text-lines: 2; /* max lines of multiline text */


    you can apply your custom options by passing options object as second parameter to 'TsGantt' constructor

    const options = new TsGanttOptions({
        multilineSelection: false,
        // other options you want to change
    // or you can use assignment expressions (come in handy for getters and formatters that refence options object itself)
    options.columnValueGetters[0] = task => 
        task.localizedNames && task.localizedNames[options.locale] || task.name; // value getter implementation for first column
    // esm chart init with options
    const chart = new TsGantt("#container-selector", options); 
    // umd chart init with options
    const chart = new tsGantt.TsGantt("#container-selector", options);
    // ⚠️chart class in not designed to allow changes in options instance after the chart initialization.
    // such changes can lead to unpredictable behavior.
    // to change locale, scale and display mode use appropriate TsGantt instance methods.
    // if it's very necessary to change other options after chart init then you should destroy old chart instance and create new one.
    this.chart = new TsGantt("#container-selector", options);
    ℹ️ complete list of 'TsGanttOptions' class properties you can use

       // some default values ommited for brevity. you can always see them in 'TsGanttOptions' source code
      multilineSelection = true; // allow multiple rows to be selected at the same time
      useCtrlKeyForMultilineSelection = false; // enable using ctrl key to select multiple rows
      drawTodayLine = true; // draw a vertical line on chart that represents today  
      highlightRowsDependingOnTaskState = true; // change row text color depending on task state
      // columns order: "Name", "Progress", "Start date planned", "End date planned",
      // "Start date actual", "End date actual", "Duration planned", "Duration actual"
      columnsMinWidthPx: number[]; // array of 8 values, one for each of 8 columns. 0 to disable column
      columnsContentAlign: ("start" | "center" | "end")[]; // array of 8 values, one for each of 8 columns.
      separatorWidthPx = 5; // vertical central line width
      headerHeightPx = 90; // lower values are not recommended, but you can still try
      rowHeightPx = 40; // lower values are not recommended, but you can still try
      borderWidthPx = 1;
      barStrokeWidthPx = 2;
      barMarginPx = 2;
      barCornerRadiusPx = 6;
      // special row symbols. you can also use some HTML code
      rowSymbols: TsGanttRowSymbols = {childless: "◆", collapsed: "⬘", expanded: "⬙"};
      chartShowProgress = true; // indicating progress percentage on chart bar using different color
      chartDisplayMode: "planned" | "actual" | "both";
      chartScale: "day" | "week" | "month" | "year";
      // optimal spare space on timeline edges in days
      chartDateOffsetDays: {[key: string]: number} = {"day": 14, "week": 60, "month": 240, "year": 730};
      // minimal spare space on timeline edges in days
      // chart timeline is redrawn only when trespassing minimal distance to chart edge to nearest bar
      chartDateOffsetDaysMin: {[key: string]: number} = {"day": 7, "week": 30, "month": 120, "year": 365};
      // width of 1 day on timeline. not recommended to use lower values than default
      chartDayWidthPx: {[key: string]: number} = {"day": 60, "week": 20, "month": 3, "year": 1};
      locale = "en"; // default locale
      localeDecimalSeparator: {[key: string]: string} = {en: ".", uk: ",", ru: ","};
      // you can provide any format strings that supported by dayjs
      localeDateFormat: {[key: string]: string} = {en: "MM/DD/YYYY", uk: "DD.MM.YYYY", ru: "DD.MM.YYYY"};
      localeFirstWeekDay: {[key: string]: number} = {en: 0, uk: 1, ru: 1}; // Sunday is 0
      localeDateMonths: {[key: string]: string[]}; // array of 12 string values for each locale. eg ["January", "February", ...etc]  
      localeDateDays: {[key: string]: string[]}; // array of 7 string values for each locale. eg ["Sunday", "Monday", ...etc]
      localeDateDaysShort: {[key: string]: string[]}; // array of 7 string values for each locale. eg ["Su", "Mo", ...etc]
      localeDateScale: {[key: string]: string[]}; // array of 3 string values for each locale. eg ["Weeks", "Months", "Years"]
      localeHeaders: {[key: string]: string[]}; // array of 8 string values for each locale
      localeDurationFormatters: {[key: string]: (duration: number) => string}; // duration formatter function for each locale
      // default column value getters return localized values by taking into account all the properties assigned above
      // but you can provide your own ones if you need more complex output 
      // returned value is assigned to cell's innerHTML property. so you can use html tags
      columnValueGetters: ((a: TsGanttTask) => string)[]; // array of 8 string value getters for each locale
      taskComparer: (taskA: TsGanttTask, taskB: TsGanttTask) => number; // you can provide here your custom task comparer

    Event callbacks

    you can pass callbacks for chart row events using TsGantt properties shown below

    onRowClickCb: (model: TsGanttTaskModel, event: MouseEvent) => void;
    onRowDoubleClickCb: (model: TsGanttTaskModel, event: MouseEvent) => void;
    onRowContextMenuCb: (model: TsGanttTaskModel, event: MouseEvent) => void;
    onSelectionChangeCb: (models: TsGanttTaskModel[]) => void;

    context menu implementation is not provided, but you can implement your own using callback

    TODO list

    • add optional multiple row selection added in 0.2.0
    • make grid columns resizable added in 0.2.2
    • add callbacks on chart events (on row click/double click, selection change) added in 0.3.0
    • allow grid column reorder
    • add optional possibility to move/resize chart bars
    • add tooltips on bar hover
    • increase code coverage
    • optimize task change detection
    • add row virtualization (move grid to custom table implementation)


    npm i ts-gantt

    DownloadsWeekly Downloads






    Unpacked Size

    276 kB

    Total Files


    Last publish


    • avatar