npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

jordium-gantt-vue3

v1.11.3

Published

A Vue 3 Gantt chart component for project management, task scheduling, resource planning and timeline visualization.

Readme

jordium-gantt-vue3


✨ Introduction

jordium-gantt-vue3 is a modern Gantt chart component for Vue3 with built-in Resource View and Resource Planning capabilities. Manage tasks, timelines, and resource allocation in one unified interface, ideal for project scheduling and workforce planning.

Core Features

  • Resource Planning View - The only Vue 3 Gantt component with a dedicated resource view. Visualize task assignments and workload per resource (people / equipment)
  • �📊 Feature Complete - Task management, milestones, dependencies, progress tracking
  • 🎨 Theme System - Built-in light/dark themes with customizable styles
  • 🖱️ Smooth Interaction - Drag & resize, zoom, double-click edit, context menu
  • 🌍 Internationalization - Built-in Chinese/English with extensible language support
  • High Performance - Virtual scrolling, lazy loading for handling massive data
  • 💎 Type Safe - Full TypeScript support

Preview

Light Theme

Dark Theme


📦 Installation

Install using your preferred package manager:

# npm
npm install jordium-gantt-vue3

# yarn
yarn add jordium-gantt-vue3

# pnpm
pnpm add jordium-gantt-vue3

🚀 Quick Start

Import Component

Import the GanttChart component and styles:

<script setup lang="ts">
import { GanttChart } from 'jordium-gantt-vue3'
import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'
</script>

Tip: The style file only needs to be imported once in your project. It's recommended to import it in main.ts or the root component.

First Example

Create your first Gantt chart:

<template>
  <div style="height: 600px;">
    <GanttChart :tasks="tasks" :milestones="milestones" />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { GanttChart } from 'jordium-gantt-vue3'
import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'

const tasks = ref([
  {
    id: 1,
    name: 'Project Kickoff',
    startDate: '2025-01-01',
    endDate: '2025-01-10',
    progress: 100,
  },
  {
    id: 2,
    name: 'Requirements Analysis',
    startDate: '2025-01-11',
    endDate: '2025-01-20',
    progress: 80,
    predecessor: [1],
  },
  {
    id: 3,
    name: 'System Design',
    startDate: '2025-01-21',
    endDate: '2025-02-05',
    progress: 50,
    predecessor: [2],
  },
])

const milestones = ref([
  {
    id: 101,
    name: 'Project Approval',
    startDate: '2025-01-01',
    type: 'milestone',
  },
])
</script>

🎯 Try Live Demo on Github → Recommended: DOVE VPN for fast and stable access. (Note: Please use VPN services legally)

🌞 NPM Package Usage Example

Please refer to the npm-demo folder in the project. It is a standalone project that can be opened and run independently using your IDE. Before running, make sure to install the Element Plus library and the jordium-gantt-vue3 plugin package.

# npm
npm install element-plus
npm install jordium-gantt-vue3
npm run dev

📖 Component Guide

GanttChart Component

GanttChart is the core entry point of the library, providing complete Gantt chart functionality.

Basic Props

| Prop | Type | Default | Description | | --------------------------- | --------- | ------- | ------------------------------------------------------------------------- | | tasks | Task[] | [] | Array of task data | | milestones | Task[] | [] | Array of milestone data (Note: Type is Task[], must set type='milestone') | | resources v1.9.0 | Resource[] | [] | Array of resource data (used in resource planning view) | | viewMode v1.9.0 | 'task' \| 'resource' | 'task' | View mode: 'task' for task planning view | 'resource' for resource planning view | | showToolbar | boolean | true | Whether to show the toolbar | | useDefaultDrawer | boolean | true | Whether to use the built-in task edit drawer (TaskDrawer) | | useDefaultMilestoneDialog | boolean | true | Whether to use the built-in milestone edit dialog (MilestoneDialog) | | autoSortByStartDate | boolean | false | Whether to automatically sort tasks by start date | | allowDragAndResize | boolean | true | Whether to allow dragging and resizing tasks/milestones | | enableTaskRowMove | boolean | false | Whether to allow dragging and dropping TaskRow | | enableTaskListContextMenu | boolean | true | Whether to enable TaskList (TaskRow) context menu. When true: uses built-in menu if task-list-context-menu slot is not declared, uses custom menu if slot is declared; when false: context menu is completely disabled | | enableTaskBarContextMenu | boolean | true | Whether to enable TaskBar context menu. When true: uses built-in menu if task-bar-context-menu slot is not declared, uses custom menu if slot is declared; when false: context menu is completely disabled | | assigneeOptions | Array<{ key?: string \| number; value: string \| number; label: string }> | [] | Assignee dropdown options in task edit drawer | | locale v1.7.1 | 'zh-CN' \| 'en-US' | 'zh-CN' | Language setting (reactive). Component's internal language will follow changes | | theme v1.7.1 | 'light' \| 'dark' | 'light' | Theme mode (reactive). Component's theme will follow changes | | timeScale v1.7.1 | 'hour' \| 'day' \| 'week' \| 'month' \| 'quarter' \| 'year' | 'week' | Time scale (reactive). Timeline scale will follow changes | | fullscreen v1.7.1 | boolean | false | Fullscreen state control (reactive). Component's fullscreen state will follow changes | | expandAll v1.7.1 | boolean | true | Expand/collapse all tasks (reactive). All tasks' expand state will follow changes | | enableLinkAnchor v1.7.2 | boolean | true | Whether to enable Link Anchor,Default: true | | pendingTaskBackgroundColor v1.8.0 | string | '#409eff' | Background color for pending tasks' TaskBar. Supports hex color values (e.g., '#409eff'). Priority: Higher than system default, lower than Task object's barColor property | | delayTaskBackgroundColor v1.8.0 | string | '#f56c6c' | Background color for overdue tasks' TaskBar. Supports hex color values (e.g., '#f56c6c'). Priority: Higher than system default, lower than Task object's barColor property | | completeTaskBackgroundColor v1.8.0 | string | '#909399' | Background color for completed tasks' TaskBar. Supports hex color values (e.g., '#909399'). Priority: Higher than system default, lower than Task object's barColor property | | ongoingTaskBackgroundColor v1.8.0 | string | '#e6a23c' | Background color for ongoing tasks' TaskBar. Supports hex color values (e.g., '#e6a23c'). Priority: Higher than system default, lower than Task object's barColor property | | showActualTaskbar v1.8.0 | boolean | false | Whether to display actual TaskBar (shows actual execution progress below planned TaskBar) | | enableTaskbarTooltip v1.8.0 | boolean | true | Whether to enable TaskBar hover tooltip (shows task details on mouse hover) | | enableMilestoneTooltip v1.10.2 | boolean | true | Whether to enable milestone hover tooltip (shows milestone name and date on mouse hover) | | showConflicts v1.9.0 | boolean | true | Whether to display resource conflict visualization layer (shows diagonal stripe background for overload zones in resource view) | | showTaskbarTab v1.9.0 | boolean | true | Whether to display resource tab on TaskBar (shows resource allocation label on TaskBar in resource view) | | enableTaskListCollapsible v1.9.2 | boolean | true | Whether to allow collapsing/expanding the TaskList panel. When false: forcibly hides TaskList, SplitterBar and collapse button; Timeline takes full width | | taskListVisible v1.9.2 | boolean | true | Controls TaskList visibility (reactive). Only effective when enableTaskListCollapsible=true | | enableTaskDrawerAutoClose v1.9.3 | boolean | true | Whether to allow TaskDrawer to auto-close (closes on outside click or Esc key). Set to false to disable auto-close — the drawer can only be closed via its internal close button |

TaskListColumn Component Props

The TaskListColumn component is used to define task list columns in declarative mode (taskListColumnRenderMode="declarative"). Similar to Element Plus's el-table-column component.

| Prop | Type | Default | Description | | ---------- | ------------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | | prop | string | - | Column property name, used to access task object fields. Examples: 'name', 'assignee', 'progress', etc. | | label | string | - | Column header display text | | width | number \| string | - | Column width. Number represents pixels (e.g., 200), string supports percentage (e.g., '20%') | | align | 'left' \| 'center' \| 'right' | 'left' | Column content alignment | | cssClass | string | - | Custom CSS class name for column styling |

Usage Example:

<GanttChart 
  :tasks="tasks" 
  task-list-column-render-mode="declarative"
>
  <TaskListColumn prop="name" label="Task Name" width="300" />
  <TaskListColumn prop="assignee" label="Assignee" width="150" align="center" />
  <TaskListColumn prop="progress" label="Progress" width="100" align="center" />
  <TaskListColumn prop="startDate" label="Start Date" width="140" />
  <TaskListColumn prop="endDate" label="End Date" width="140" />
</GanttChart>

💡 Tips:

  • The TaskListColumn component itself does not render any content, it only declares column configuration
  • Must be used inside the GanttChart component with task-list-column-render-mode="declarative" set
  • Column display order is determined by the declaration order of TaskListColumn components
  • For detailed column content customization and slot usage, see Slots section

TaskListContextMenu Component Props

The TaskListContextMenu component is used to declaratively define the context menu for TaskList (TaskRow). Takes effect when enableTaskListContextMenu is true.

| Prop | Type | Default | Description | | ---------- | ---------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | taskType | string \| string[] | undefined | Specifies which task types should display this context menu. When not set, follows existing logic (all tasks show menu). When set, only specified types show menu. Supports single type (e.g., 'task') or multiple types (e.g., ['task', 'milestone']) |

Usage Examples:

<GanttChart 
  :tasks="tasks" 
  :enable-task-list-context-menu="true"
>
  <!-- Default behavior: all tasks show this context menu -->
  <TaskListContextMenu>
    <template #default="scope">
      <div class="custom-menu">
        <div class="menu-item" @click="editTask(scope.row)">Edit</div>
        <div class="menu-item" @click="deleteTask(scope.row)">Delete</div>
      </div>
    </template>
  </TaskListContextMenu>
  
  <!-- Only show for tasks with type='task' -->
  <TaskListContextMenu task-type="task">
    <template #default="scope">
      <div class="custom-menu">
        <div class="menu-item">Task Specific Menu</div>
      </div>
    </template>
  </TaskListContextMenu>
  
  <!-- Show for multiple types -->
  <TaskListContextMenu :task-type="['task', 'milestone']">
    <template #default="scope">
      <div class="custom-menu">
        <div class="menu-item">Task and Milestone Menu</div>
      </div>
    </template>
  </TaskListContextMenu>
</GanttChart>

💡 Tips:

  • The TaskListContextMenu component itself does not render any content, it only declares menu configuration
  • Must be used inside the GanttChart component with enable-task-list-context-menu="true" set
  • Menu positioning and visibility are automatically managed internally, users only need to focus on menu content HTML structure
  • Menu automatically closes when clicking outside or scrolling
  • For detailed slot usage, see Slots section

TaskBarContextMenu Component Props

The TaskBarContextMenu component is used to declaratively define the context menu for TaskBar (timeline task bars). Takes effect when enableTaskBarContextMenu is true.

| Prop | Type | Default | Description | | ---------- | ---------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | taskType | string \| string[] | undefined | Specifies which task types should display this context menu. When not set, follows existing logic (all tasks show menu). When set, only specified types show menu. Supports single type (e.g., 'task') or multiple types (e.g., ['task', 'milestone']) |

Usage Examples:

<GanttChart 
  :tasks="tasks" 
  :enable-task-bar-context-menu="true"
>
  <!-- Default behavior: all tasks show this context menu -->
  <TaskBarContextMenu>
    <template #default="scope">
      <div class="custom-menu">
        <div class="menu-item" @click="extendTask(scope.row)">Extend Task</div>
        <div class="menu-item" @click="moveTask(scope.row)">Move Task</div>
      </div>
    </template>
  </TaskBarContextMenu>
  
  <!-- Only show for tasks with type='task' -->
  <TaskBarContextMenu task-type="task">
    <template #default="scope">
      <div class="custom-menu">
        <div class="menu-item">Task Bar Specific Menu</div>
      </div>
    </template>
  </TaskBarContextMenu>
  
  <!-- Show for multiple types -->
  <TaskBarContextMenu :task-type="['task', 'story']">
    <template #default="scope">
      <div class="custom-menu">
        <div class="menu-item">Task and Story Menu</div>
      </div>
    </template>
  </TaskBarContextMenu>
</GanttChart>

💡 Tips:

  • The TaskBarContextMenu component itself does not render any content, it only declares menu configuration
  • Must be used inside the GanttChart component with enable-task-bar-context-menu="true" set
  • Menu positioning and visibility are automatically managed internally, users only need to focus on menu content HTML structure
  • Menu automatically closes when clicking outside or scrolling
  • For detailed slot usage, see Slots section

Configuration Object Props

For complete configuration object documentation, see ⚙️ Configuration & Customization section.

| Prop | Type | Default | Description | | ---------------- | ---------------------------- | ----------------------------------------------------------------------- | ---------------------------- | | toolbarConfig | ToolbarConfig | {} | Toolbar configuration | | taskListConfig | TaskListConfig | undefined | Task list configuration | | resourceListConfig v1.9.0 | ResourceListConfig | undefined | Resource list configuration | | taskBarConfig | TaskBarConfig | undefined | Task bar style configuration | | localeMessages | Partial<Messages['zh-CN']> | undefined | Custom localization messages | | workingHours | WorkingHours | { morning: { start: 8, end: 11 }, afternoon: { start: 13, end: 17 } } | Working hours configuration | | scaleConfigs v1.11.0 | { [scale: TimelineScale]?: ScaleConfigOption } | undefined | Custom display configuration per time scale (cell width, header formatters, buffers, etc.), see scaleConfigs (Timeline Scale Configuration) |

Callback Props

| Prop | Type | Description | | -------------------- | ------------------------------------ | ------------------------------------------------------------------------------------ | | onTodayLocate | () => void | Toolbar "Today" button click callback | | onExportCsv | () => boolean \| void | Toolbar "Export CSV" button click callback, return false to prevent default export | | onExportPdf | () => void | Toolbar "Export PDF" button click callback | | onLanguageChange | (lang: 'zh-CN' \| 'en-US') => void | Language switch callback | | onThemeChange | (isDark: boolean) => void | Theme switch callback | | onFullscreenChange | (isFullscreen: boolean) => void | Fullscreen toggle callback | | onExpandAll | () => void | Toolbar "Expand All" button click callback | | onCollapseAll | () => void | Toolbar "Collapse All" button click callback |

Component Events

For complete event documentation, see:

Event List Overview:

| Event Name | Parameters | Description | | ------------------------ | --------------------------------- | -------------------------------------- | | add-task | - | Clicked toolbar "Add Task" button | | task-click | (task: Task, event: MouseEvent) | Clicked task | | task-double-click | (task: Task) | Double-clicked task | | task-added | { task: Task } | Triggered after task added | | task-updated | { task: Task } | Triggered after task updated | | task-deleted | { task: Task } | Triggered after task deleted | | taskbar-drag-end | (task: Task) | Task drag ended | | taskbar-resize-end | (task: Task) | Task resize ended | | predecessor-added | { targetTask, newTask } | Added predecessor task | | successor-added | { targetTask, newTask } | Added successor task | | timer-started | (task: Task) | Task timer started | | timer-stopped | (task: Task) | Task timer stopped | | add-milestone | - | Clicked toolbar "Add Milestone" button | | milestone-saved | (milestone: Task) | Milestone saved | | milestone-deleted | { milestoneId: number } | Milestone deleted | | milestone-icon-changed | { milestoneId, icon } | Milestone icon changed | | milestone-drag-end | (milestone: Task) | Milestone drag ended | | task-row-moved | payload: { draggedTask: Task, targetTask: Task, position: 'after' \| 'child', oldParent: Task \| null, newParent: Task \| null } | TaskRow drag ended (optional) | | taskbar-resource-change v1.9.0 | payload: { task: Task, oldResourceId: string \| number, newResourceId: string \| number } | Task moved across resources (dragging task to another resource row in resource view) |

Example 1: Simplest Gantt Chart

<template>
  <div style="height: 600px;">
    <GanttChart :tasks="tasks" :assignee-options="assigneeOptions" />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { GanttChart } from 'jordium-gantt-vue3'
import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'

const tasks = ref([
  {
    id: 1,
    name: 'Task 1',
    startDate: '2025-01-01',
    endDate: '2025-01-10',
    progress: 100,
  },
])

const assigneeOptions = ref([
  { value: 'alice', label: 'Alice' },
  { value: 'bob', label: 'Bob' },
  { value: 'charlie', label: 'Charlie' },
])
</script>

Example 2: Gantt Chart with Milestones

<template>
  <div style="height: 600px;">
    <GanttChart :tasks="tasks" :milestones="milestones" :assignee-options="assigneeOptions" />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { GanttChart } from 'jordium-gantt-vue3'
import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'

const tasks = ref([
  {
    id: 1,
    name: 'Project Kickoff',
    startDate: '2025-01-01',
    endDate: '2025-01-10',
    progress: 100,
  },
])

const milestones = ref([
  {
    id: 101,
    name: 'Project Approval',
    startDate: '2025-01-01',
    type: 'milestone',
    icon: 'diamond',
  },
])

const assigneeOptions = ref([
  { value: 'alice', label: 'Alice' },
  { value: 'bob', label: 'Bob' },
  { value: 'charlie', label: 'Charlie' },
])
</script>

Example 3: Hide Toolbar, Custom Control Buttons with Event Binding

<template>
  <div>
    <!-- Custom toolbar -->
    <div class="custom-toolbar">
      <button @click="addTask">Add Task</button>
      <button @click="addMilestone">Add Milestone</button>
    </div>

    <!-- Gantt chart component with hidden built-in toolbar -->
    <div style="height: 600px;">
      <GanttChart
        :tasks="tasks"
        :milestones="milestones"
        :show-toolbar="false"
        :assignee-options="assigneeOptions"
        @task-added="handleTaskAdded"
        @milestone-saved="handleMilestoneSaved"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { GanttChart } from 'jordium-gantt-vue3'
import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'

const tasks = ref([])
const milestones = ref([])

const assigneeOptions = ref([
  { value: 'alice', label: 'Alice' },
  { value: 'bob', label: 'Bob' },
  { value: 'charlie', label: 'Charlie' },
])

const addTask = () => {
  const newTask = {
    id: Date.now(),
    name: 'New Task',
    startDate: new Date().toISOString().split('T')[0],
    endDate: new Date().toISOString().split('T')[0],
    progress: 0,
  }
  tasks.value.push(newTask)
}

const addMilestone = () => {
  const newMilestone = {
    id: Date.now(),
    name: 'New Milestone',
    startDate: new Date().toISOString().split('T')[0],
    type: 'milestone',
  }
  milestones.value.push(newMilestone)
}

const handleTaskAdded = e => {
  console.log('Task added:', e.task)
}

const handleMilestoneSaved = milestone => {
  console.log('Milestone saved:', milestone)
}
</script>

Example 4: External Component State Control (TimeScale, Fullscreen, Expand/Collapse, Locale, Theme)

Control component state through reactive Props binding. Component state will automatically follow Props changes.

<template>
  <div>
    <!-- External control panel -->
    <div class="control-panel">
      <button @click="propsFullscreen = !propsFullscreen">Toggle Fullscreen</button>
      <button @click="propsExpandAll = !propsExpandAll">Expand/Collapse All</button>
      <button @click="propsLocale = 'zh-CN'">中文</button>
      <button @click="propsLocale = 'en-US'">English</button>
      <button @click="propsTimeScale = 'day'">Day View</button>
      <button @click="propsTimeScale = 'week'">Week View</button>
      <button @click="propsTimeScale = 'month'">Month View</button>
      <button @click="propsTheme = 'light'">Light Theme</button>
      <button @click="propsTheme = 'dark'">Dark Theme</button>
    </div>

    <!-- Gantt chart component -->
    <div style="height: 600px;">
      <GanttChart
        :tasks="tasks"
        :milestones="milestones"
        :locale="propsLocale"
        :theme="propsTheme"
        :time-scale="propsTimeScale"
        :fullscreen="propsFullscreen"
        :expand-all="propsExpandAll"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { GanttChart } from 'jordium-gantt-vue3'
import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'

const tasks = ref([
  { id: 1, name: 'Task 1', startDate: '2025-01-01', endDate: '2025-01-10', progress: 50 },
  { id: 2, name: 'Task 2', startDate: '2025-01-05', endDate: '2025-01-15', progress: 30 },
])
const milestones = ref([])

// Props control variables
const propsLocale = ref<'zh-CN' | 'en-US'>('zh-CN')
const propsTheme = ref<'light' | 'dark'>('light')
const propsTimeScale = ref<'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year'>('week')
const propsFullscreen = ref(false)
const propsExpandAll = ref(false)
</script>

Task Management

Tasks are the core elements of the Gantt chart. The component provides complete CRUD operation support for tasks, including adding, editing, deleting tasks, and rich interactive events.

Task Data Structure

| Field | Type | Required | Default | Description | | ------------------ | ---------- | -------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | id | number | ✅ | - | Unique task identifier | | name | string | ✅ | - | Task name | | startDate | string | - | - | Start date, format: 'YYYY-MM-DD' or 'YYYY-MM-DD HH:mm' | | endDate | string | - | - | End date, format: 'YYYY-MM-DD' or 'YYYY-MM-DD HH:mm' | | progress | number | - | 0 | Task progress, range 0-100 | | predecessor | number[] | - | - | Array of predecessor task IDs, standard format: [1, 2, 3]Compatible formats: Also supports string '1,2,3' or string array ['1', '2', '3'], component will auto-parse | | assignee | string | string[] v1.8.0 | - | - | Task assignee, used as the value binding for the assignee dropdown menu. Supports single assignee (string) or multiple assignees (string array) | | assigneeName | string | string[] v1.8.0 | - | - | Task assignee name, automatically obtained from the label in the bound assigneeOptions dataset; for custom display, you can set it in the task-added callback event of GanttChart. Supports single name (string) or multiple names (string array) | | avatar | string | string[] v1.8.0 | - | - | Avatar URL of task assignee. Supports single avatar (string) or multiple avatars (string array) | | estimatedHours | number | - | - | Estimated hours | | actualHours | number | - | - | Actual hours | | parentId | number | - | - | Parent task ID, used for task grouping | | children | Task[] | - | - | Array of child tasks | | collapsed | boolean | - | false | Whether child tasks are collapsed | | isParent | boolean | - | - | Whether this is a parent task | | type | string | - | - | Task type, 'milestone' for milestone, 'milestone-group' for milestone group | | description | string | - | - | Task description | | icon | string | - | 'diamond' | Task icon (for milestones), options: 'diamond', 'flag', 'star', 'rocket', etc. | | level | number | - | 0 | Task level (auto-calculated) | | isTimerRunning | boolean | - | false | Whether timer is running | | timerStartTime | number | - | - | Timer start time (timestamp) | | timerEndTime | number | - | - | Timer end time (timestamp) | | timerStartDesc | string | - | - | Description filled when timer starts | | timerElapsedTime | number | - | 0 | Elapsed time (milliseconds) | | isEditable | boolean | - | true | Whether individual task is editable (draggable, resizable), overrides global allowDragAndResize | | [key: string] | unknown | - | - | Supports custom property extensions, can add any additional fields |

Custom Property Extensions: The Task interface supports adding arbitrary custom fields, such as: priority, tags, status, department, and other business-related fields.

Predecessor Field Notes:

  • Standard format (recommended): predecessor: [1, 2, 3] - number array Compatible format 1: predecessor: '1,2,3' - comma-separated string
  • Compatible format 2: predecessor: ['1', '2', '3'] - string array
  • Component will automatically parse all formats into number array
  • No predecessors: use empty array [], empty string '', or don't set this field

Task-Related Props

| Prop | Type | Default | Description | | --------------------- | ---------------- | ----------- | --------------------------------------------------------------------------------------------- | | tasks | Task[] | [] | Array of task data | | useDefaultDrawer | boolean | true | Whether to use built-in task edit drawer (TaskDrawer) | | taskBarConfig | TaskBarConfig | {} | Task bar style configuration, see TaskBarConfig Configuration | | taskListConfig | TaskListConfig | undefined | Task list configuration, see TaskListConfig Configuration | | autoSortByStartDate | boolean | false | Whether to automatically sort tasks by start date | | enableTaskRowMove | boolean | false | Whether to alloww dragging and dropping TaskRow | | assigneeOptions | Array<{ key?: string \| number; value: string \| number; label: string }> | [] | Assignee dropdown options in task edit drawer | | taskListColumnRenderMode | 'default' \| 'declarative' | 'default' | Task list column render mode. 'default': Use TaskListColumnConfig configuration (compatibility mode, will be gradually deprecated); 'declarative': Use TaskListColumn component for declarative column definition (recommended). See TaskListColumn Declarative Column Definition | | taskListRowClassName | string \| ((task: Task) => string) | undefined | Custom CSS class name for task rows. Can be a string or a function that returns a string. Note: Row height is managed internally by the component, custom height styles will not take effect | | taskListRowStyle | CSSProperties \| ((task: Task) => CSSProperties) | undefined | Custom inline styles for task rows. Can be a style object or a function that returns a style object. Note: Row height and width are managed internally by the component, custom width/height styles will not take effect |

Configuration Notes:

  • Default mode: useDefaultDrawer=true (default), double-click task to auto-open built-in TaskDrawer
  • Custom editor: useDefaultDrawer=false disables built-in drawer, listen to @task-double-click event to open custom editor
  • Read-only mode: useDefaultDrawer=false and don't listen to @task-double-click event, user double-click task has no response

Task Events

💡 Event-Driven Architecture: Component adopts pure event-driven design. All user operations (add, edit, delete, drag, etc.) will trigger corresponding events for easy external listening and handling.

| Event Name | Parameters | When Triggered | Description | | -------------------- | ----------------------------------------- | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | add-task | - | When clicking toolbar "Add Task" button | Can be used for custom add task logic. If useDefaultDrawer=true, component will auto-open built-in TaskDrawer | | task-click | (task: Task, event: MouseEvent) => void | When clicking task bar | Triggered on single-click task | | task-double-click | (task: Task) => void | When double-clicking task bar | Double-click task always triggers. When useDefaultDrawer=true, component will additionally open built-in editor; when false, won't open. Event triggering is independent of property value | | task-added | { task: Task } | After task added | Triggered after adding task via built-in TaskDrawer. Note: Component has auto-updated tasks data, external only needs to listen to this event for additional processing (like calling API to save) | | task-updated | { task: Task } | After task updated | Triggered after updating task via built-in TaskDrawer or drag. Note: Component has auto-updated tasks data, external only needs to listen to this event for additional processing | | task-deleted | { task: Task } | After task deleted | Triggered after deleting task via built-in TaskDrawer. Note: Component has auto-updated tasks data, external only needs to listen to this event for additional processing | | taskbar-drag-end | (task: Task) => void | When task bar drag ends | Task position changed, startDate and endDate updated. Note: Component has auto-updated tasks data | | taskbar-resize-end | (task: Task) => void | When task bar resize ends | Task duration changed, endDate updated. Note: Component has auto-updated tasks data | | predecessor-added | { targetTask: Task, newTask: Task } | After adding predecessor via context menu | targetTask is the task to which predecessor is added, newTask is the newly created predecessor task | | successor-added | { targetTask: Task, newTask: Task } | After adding successor via context menu | targetTask is the original task, newTask is the newly created successor task (its predecessor already contains targetTask.id) | | timer-started | (task: Task) => void | When task timer starts | Start recording task hours | | timer-stopped | (task: Task) => void | When task timer stops | Stop recording task hours | | task-row-moved | payload: { draggedTask: Task, targetTask: Task, position: 'after' \| 'child', oldParent: Task \| null, newParent: Task \| null } | TaskRow drag ended (optional) | Component has automatically completed data movement and TaskList/Timeline sync via object reference mutation. Listening to this event is completely optional, only for showing messages, calling API, etc. position: 'after'=same level, 'child'=as child |

Data Synchronization Notes:

  • Component auto-updates internally: For all task CRUD operations, component will auto-update props.tasks data
  • Events are for notification only: External event listeners are mainly for: showing messages, calling backend APIs, updating other related data, etc.
  • Avoid duplicate operations: Don't modify tasks data again in event handlers, otherwise it will cause duplicate updates

Example 1: Basic Task Operations

<template>
  <div style="height: 600px;">
    <GanttChart
      :tasks="tasks"
      :assignee-options="assigneeOptions"
      @add-task="handleAddTask"
      @task-added="handleTaskAdded"
      @task-updated="handleTaskUpdated"
      @task-deleted="handleTaskDeleted"
      @task-click="handleTaskClick"
      @taskbar-drag-end="handleTaskDragEnd"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { GanttChart } from 'jordium-gantt-vue3'
import type { Task } from 'jordium-gantt-vue3'
import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'

const tasks = ref<Task[]>([
  {
    id: 1,
    name: 'Project Planning',
    startDate: '2025-01-01',
    endDate: '2025-01-10',
    progress: 100,
    assignee: 'Alice',
    estimatedHours: 40,
  },
  {
    id: 2,
    name: 'Requirements Analysis',
    startDate: '2025-01-11',
    endDate: '2025-01-20',
    progress: 60,
    assignee: 'Bob',
    predecessor: [1], // Depends on task 1
  },
])

const assigneeOptions = ref([
  { value: 'alice', label: 'Alice' },
  { value: 'bob', label: 'Bob' },
  { value: 'charlie', label: 'Charlie' },
])

// Toolbar "Add Task" button click event
const handleAddTask = () => {
  console.log('Preparing to add task...')
  // Component will auto-open TaskDrawer (if useDefaultDrawer=true)
  // Can also execute custom logic here, like showing messages
}

// Task add event (added via built-in drawer)
const handleTaskAdded = (e: { task: Task }) => {
  console.log('Task added:', e.task)
  // Note: Component has auto-added task to tasks array
  // Only need to call backend API to save here
  // await api.createTask(e.task)
}

// Task update event (updated via built-in drawer or drag)
const handleTaskUpdated = (e: { task: Task }) => {
  console.log('Task updated:', e.task)
  // Note: Component has auto-updated task data in tasks array
  // Only need to call backend API to update here
  // await api.updateTask(e.task.id, e.task)
}

// Task delete event
const handleTaskDeleted = (e: { task: Task }) => {
  console.log('Task deleted:', e.task)
  // Note: Component has auto-removed task from tasks array
  // Only need to call backend API to delete here
  // await api.deleteTask(e.task.id)
}

// Task click event
const handleTaskClick = (task: Task) => {
  console.log('Clicked task:', task.name)
}

// Task drag end event
const handleTaskDragEnd = (task: Task) => {
  console.log('Task drag completed, new dates:', task.startDate, 'to', task.endDate)
  // Can call backend API here to save new dates
}
</script>

Example 2: Task Dependencies (Predecessors/Successors)

Tasks can configure predecessors via the predecessor field, and the component will automatically draw dependency lines:

<template>
  <GanttChart
    :tasks="tasks"
    :assignee-options="assigneeOptions"
    @predecessor-added="handlePredecessorAdded"
    @successor-added="handleSuccessorAdded"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { GanttChart } from 'jordium-gantt-vue3'
import type { Task } from 'jordium-gantt-vue3'
import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'

const tasks = ref<Task[]>([
  {
    id: 1,
    name: 'Requirements Analysis',
    startDate: '2025-01-01',
    endDate: '2025-01-10',
    progress: 100,
    predecessor: [], // No predecessors
  },
  {
    id: 2,
    name: 'System Design',
    startDate: '2025-01-11',
    endDate: '2025-01-20',
    progress: 80,
    predecessor: [1], // Depends on task 1 (Requirements Analysis)
  },
  {
    id: 3,
    name: 'Database Design',
    startDate: '2025-01-11',
    endDate: '2025-01-18',
    progress: 90,
    predecessor: [1], // Depends on task 1
  },
  {
    id: 4,
    name: 'Frontend Development',
    startDate: '2025-01-21',
    endDate: '2025-02-10',
    progress: 60,
    predecessor: [2], // Depends on task 2 (System Design)
  },
  {
    id: 5,
    name: 'Backend Development',
    startDate: '2025-01-19',
    endDate: '2025-02-08',
    progress: 70,
    predecessor: [2, 3], // Depends on both task 2 and 3
  },
  {
    id: 6,
    name: 'Integration Testing',
    startDate: '2025-02-11',
    endDate: '2025-02-20',
    progress: 30,
    predecessor: [4, 5], // Depends on frontend and backend development completion
  },
])

const assigneeOptions = ref([
  { value: 'alice', label: 'Alice' },
  { value: 'bob', label: 'Bob' },
  { value: 'charlie', label: 'Charlie' },
])

// Triggered when adding predecessor via context menu
const handlePredecessorAdded = (event: { targetTask: Task; newTask: Task }) => {
  console.log(`Task [${event.targetTask.name}] added predecessor [${event.newTask.name}]`)
  // Component will auto-update targetTask's predecessor array (append new task ID)
  // Can call backend API here to save dependency relationship
  // await api.addTaskDependency(event.targetTask.id, event.newTask.id)
}

// Triggered when adding successor via context menu
const handleSuccessorAdded = (event: { targetTask: Task; newTask: Task }) => {
  console.log(`Task [${event.targetTask.name}] added successor [${event.newTask.name}]`)
  // Component will auto-update newTask's predecessor array (add targetTask.id)
  // Can call backend API here to save dependency relationship
  // await api.addTaskDependency(event.newTask.id, event.targetTask.id)
}
</script>

Dependency Relationship Notes:

  • predecessor field supports multiple formats:
    • Standard format (recommended): [1, 2, 3] - number array
    • Compatible format 1: '1,2,3' - comma-separated string
    • Compatible format 2: ['1', '2', '3'] - string array
    • Component will automatically parse all formats
  • Predecessor task: Task that must be completed first (e.g., design must be done before development)
  • Successor task: Task that depends on current task (current task is a predecessor for other tasks)
  • Component will automatically draw dependency lines from predecessor tasks to dependent tasks
  • Can add/delete predecessor and successor tasks via built-in context menu
  • When deleting tasks via built-in menu, component will automatically clean up related dependency references
  • No predecessors: use empty array [], empty string '', or don't set predecessor field

Example 3: Hide Toolbar, Use Custom Buttons to Trigger Events

Suitable for scenarios requiring complete custom control bar:

<template>
  <div>
    <!-- Custom control bar -->
    <div class="custom-toolbar">
      <button @click="triggerAddTask">Add Task</button>
      <button @click="triggerAddMilestone">Add Milestone</button>
      <!-- Other custom buttons... -->
    </div>

    <!-- Gantt chart component with hidden built-in toolbar -->
    <GanttChart
      :tasks="tasks"
      :milestones="milestones"
      :show-toolbar="false"
      :use-default-drawer="true"
      :use-default-milestone-dialog="true"
      :assignee-options="assigneeOptions"
      @add-task="handleAddTask"
      @add-milestone="handleAddMilestone"
      @task-added="handleTaskAdded"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { GanttChart } from 'jordium-gantt-vue3'
import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'

const tasks = ref([])
const milestones = ref([])

const assigneeOptions = ref([
  { value: 'alice', label: 'Alice' },
  { value: 'bob', label: 'Bob' },
  { value: 'charlie', label: 'Charlie' },
])

// Custom button triggers event (component will respond and open built-in editor)
const triggerAddTask = () => {
  // Directly trigger component's add-task event
  // Since useDefaultDrawer=true, component will auto-open TaskDrawer
}

const triggerAddMilestone = () => {
  // Directly trigger component's add-milestone event
  // Since useDefaultMilestoneDialog=true, component will auto-open MilestoneDialog
}

// Listen to event handling logic
const handleAddTask = () => {
  console.log('Preparing to add task (triggered by custom button)')
}

const handleAddMilestone = () => {
  console.log('Preparing to add milestone (triggered by custom button)')
}

const handleTaskAdded = e => {
  console.log('Task added:', e.task)
  // Call API to save...
}
</script>

💡 Flexibility Design:

  • Show toolbar + default editor: Simplest out-of-the-box approach
  • Hide toolbar + custom buttons + default editor: Custom control bar style while keeping default edit functionality
  • Hide toolbar + custom buttons + custom editor: Fully customize all interaction logic

Example 4: Task Row Drag and Drop Sorting

Allow users to adjust task hierarchy and order by dragging TaskRow:

<template>
  <div style="height: 600px;">
    <GanttChart
      :tasks="tasks"
      :enable-task-row-move="true"
      :assignee-options="assigneeOptions"
      @task-row-moved="handleTaskRowMoved"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { GanttChart } from 'jordium-gantt-vue3'
import type { Task } from 'jordium-gantt-vue3'
import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'

const tasks = ref<Task[]>([
  {
    id: 1,
    name: 'Project Planning',
    startDate: '2025-01-01',
    endDate: '2025-01-10',
    progress: 100,
  },
  {
    id: 2,
    name: 'Requirements Analysis',
    startDate: '2025-01-11',
    endDate: '2025-01-20',
    progress: 60,
    parentId: 1,
  },
  {
    id: 3,
    name: 'System Design',
    startDate: '2025-01-21',
    endDate: '2025-01-30',
    progress: 40,
  },
])

const assigneeOptions = ref([
  { value: 'alice', label: 'Alice' },
  { value: 'bob', label: 'Bob' },
  { value: 'charlie', label: 'Charlie' },
])

// Task row drag completed event (optional)
const handleTaskRowMoved = async (payload: {
  draggedTask: Task
  targetTask: Task
  position: 'after' | 'child'
  oldParent: Task | null
  newParent: Task | null
}) => {
  const { draggedTask, targetTask, position, oldParent, newParent } = payload
  
  // Component has automatically completed task move, parentId update and TaskList/Timeline sync
  // Listening to this event is completely optional, only for:
  
  // 1. Show custom notification message
  const oldParentName = oldParent?.name || 'Root'
  const newParentName = newParent?.name || 'Root'
  const positionText = position === 'after' ? 'after target task' : 'as child of target task'
  showMessage(`Task [${draggedTask.name}] moved from [${oldParentName}] to [${newParentName}] (${positionText})`, 'success')
  
  // 2. Call backend API to save new task hierarchy
  try {
    await api.updateTaskHierarchy({
      taskId: draggedTask.id,
      targetTaskId: targetTask.id,
      position: position,
      oldParentId: oldParent?.id,
      newParentId: newParent?.id,
    })
  } catch (error) {
    console.error('Save task hierarchy failed:', error)
    showMessage('Save failed, please refresh page', 'error')
  }
  
  // 3. Trigger other business logic (like updating related data, recording operation logs, etc.)
  // ...
}
</script>

Drag and Drop Sorting Notes:

  • Enable Dragging: Set enable-task-row-move="true" to enable task row dragging (default is false)
  • Dragging Algorithms (automatically executed by component):
    • Algorithm 1 (Place After): When target task has no children, dragged task will be placed after target task (same level), position='after'
    • Algorithm 2 (As Child): When target task has children, dragged task will become first child of target task, position='child'
  • Visual Feedback:
    • Semi-transparent following element displayed while dragging
    • Blue border hint shown when hovering over valid target tasks
    • Tasks without children show blue bottom border
    • Tasks with children show blue border on all sides
  • Auto Sync: Component internally mutates props.tasks via object reference, automatically completing task move, parentId update, children array adjustment, and TaskList/Timeline synchronization
  • Event Listening (Optional):
    • task-row-moved event is completely optional, only used for showing messages, calling API to save, recording logs, etc.
    • No need to manually update tasks.value, component has automatically completed data synchronization
  • Event Parameters:
    • draggedTask: The dragged task
    • targetTask: The target task
    • position: Drop position ('after' or 'child')
    • oldParent: Original parent task (null means root)
    • newParent: New parent task (null means root)
  • Constraints:
    • Cannot drag onto itself
    • Cannot drag onto its own child tasks (avoid circular reference)
    • Milestones and milestone groups cannot be dragged

Resource Management v1.9.0

Resource management is used to manage human resources or equipment in a project, supporting task allocation, resource load analysis, and conflict detection in resource view. Switch to resource planning view using the viewMode="resource" prop.

Core Features:

  • 📊 Resource View: Display task allocation by resource dimension
  • 🎯 Load Analysis: Real-time display of resource utilization and overload status
  • ⚠️ Conflict Detection: Automatically detect resource time conflicts (e.g., Task A:40% + Task B:40% + Task C:30% = 110% overload)
  • 🎨 Visualization: Diagonal stripe background marks conflict zones, resource tabs show utilization percentage
  • 🔄 Cross-Resource Move: Support dragging tasks to different resource rows for reallocation

View Limitations:

  • Task Links Disabled: Resource view does not display predecessor/successor relationship lines between tasks, as resource view