organization-chart-vue3

A lightweight, interactive organization chart component for Vue 3 with collapsible nodes, TypeScript types, custom slots, and selection events
5,750 5
Install
npm install organization-chart-vue3
Latest Version:1.2.2
Vue:3
License:MIT
Last Updated:Jul 21, 2026
Links: GitHub  ·  npm
Maintainer: leejam

Organization-Chart-Vue3

NPM

A lightweight, interactive organization chart component for Vue 3 with collapsible nodes, TypeScript types, custom slots, and selection events.

Organization Chart Vue3 renders hierarchical team and company structures with no framework dependency beyond Vue. It supports expandable branches, custom node and member templates, stable tree paths, and typed event payloads.

Features

  • Interactive expand and collapse controls
  • TypeScript definitions for nodes, members, and events
  • Custom node-title and member slots
  • Typed select events with stable IDs and tree paths
  • Vue 3.3.4 or later

Live Demo

Try it here:

Organization-Chart-Vue3 DEMO

Install

Minimum supported Vue version: 3.3.4

npm i organization-chart-vue3

Basic Usage

<template>
  <OrganizationChart
    :data="orgData"
    @click-node="handleLegacyClick"
    @select="handleSelect"
  />
</template>

<script>
import OrganizationChart from "organization-chart-vue3";
import "organization-chart-vue3/style.css";

export default {
  components: {
    OrganizationChart,
  },
  data() {
    return {
      orgData: {
        id: "company",
        title: "CEO",
        member: [
          {
            id: "oliver",
            name: "Oliver",
            add: "Chief Executive Officer",
          },
        ],
        children: [
          {
            id: "engineering",
            title: "Engineering",
            member: [
              {
                id: "emma",
                name: "Emma",
                add: "CTO",
              },
            ],
            children: [
              {
                id: "frontend",
                title: "Frontend",
              },
            ],
          },
        ],
      },
    };
  },
  methods: {
    handleLegacyClick(payload) {
      console.log("legacy click-node payload", payload);
    },
    handleSelect(payload) {
      console.log("typed select payload", payload);
    },
  },
};
</script>

script setup + TypeScript

<template>
  <OrganizationChart :data="orgData" @select="handleSelect" />
</template>

<script setup lang="ts">
import OrganizationChart from "organization-chart-vue3";
import "organization-chart-vue3/style.css";
import type {
  OrganizationChartNode,
  OrganizationChartSelectPayload,
} from "organization-chart-vue3";

const orgData: OrganizationChartNode = {
  id: "company",
  title: "CEO",
  member: [
    {
      id: "oliver",
      name: "Oliver",
      add: "Chief Executive Officer",
    },
  ],
  children: [
    {
      id: "engineering",
      title: "Engineering",
      member: [
        {
          name: "Emma",
          add: "CTO",
        },
      ],
      children: [
        {
          id: "frontend",
          title: "Frontend",
        },
      ],
    },
  ],
};

function handleSelect(payload: OrganizationChartSelectPayload) {
  if (payload.kind === "member") {
    console.log("member selected", payload.member?.name);
    return;
  }

  console.log("node selected", payload.node.title);
}
</script>

Event Payload

select is the recommended event. It emits a typed payload:

type OrganizationChartSelectPayload = {
  kind: "node" | "member";
  node: OrganizationChartNode;
  member?: OrganizationChartMember;
  id?: string;
  path: string[];
};
  • Clicking a node title emits { kind: "node", node, id: node.id, path }
  • Clicking a member row emits { kind: "member", node, member, id, path }
  • click-node is still supported for backward compatibility and emits the raw node or member object

Props

  • data: OrganizationChartNode
  • defaultExpandAll?: boolean Default is true

Slots

  • node-title Receives { node, depth, path }
  • member Receives { node, member, depth, path }

Example:

<OrganizationChart :data="orgData">
  <template #node-title="{ node, depth }">
    <span>{{ depth + 1 }}. {{ node.title }}</span>
  </template>

  <template #member="{ member }">
    <div class="member-card">
      <strong>{{ member.name }}</strong>
      <span>{{ member.add }}</span>
    </div>
  </template>
</OrganizationChart>

Data Shape

interface OrganizationChartMember {
  id?: string;
  name?: string;
  add?: string;
  image_url?: string;
}

interface OrganizationChartNode {
  id?: string;
  title: string;
  member?: OrganizationChartMember[];
  children?: OrganizationChartNode[];
  titleClass?: string | string[];
  contentClass?: string | string[];
}

id is optional, but recommended. It gives the chart stable keys for expand state and makes AI-generated data updates more predictable.

Copyright (c) 2023-present, LeeJam

Related Packages

vue-organization-chart

organization chart component based vuejs

120,364 303
vue-okr-tree

一个特殊布局模式结构的`vue Tree`组件

3,749 650
@efont/vue-baselib

vue-baselib

2,721 2
@phronesyss/bar-chart

This is the first part of the admetricks challenge, that consist on creating two...

407 0

Version History

Version Released Vue License
1.2.2 >=3.3.4 <4 MIT
1.2.1 >=3.3.4 <4 MIT
1.2.0 >=3.3.4 <4 MIT
1.1.2 ^3.3.4 MIT
1.1.1 ^3.3.4 MIT