JSFiddle - React, Tailwind, and code Playground

by Rajesh Danabal

HTML

<svg id="svg" width="100%" height="100%"></svg>

<script src="https://d3js.org/d3.v7.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/d3-flextree.min.js"></script>

JavaScript

// --- Sample data with items per node ---
const data = {
  name: "Root",
  w: 160, h: 120,
  items: [
    { id: "root1", label: "Root-Task A" },
    { id: "root2", label: "Root-Task B" }
  ],
  children: [
    {
      name: "Alpha", w: 160, h: 120,
      items: [
        { id: "a1", label: "Alpha-1" },
        { id: "a2", label: "Alpha-2" }
      ],
      children: [
        { name: "A-1", w: 140, h: 100, items: [{id:"a1-1", label:"Leaf"}] },
        { name: "A-2", w: 140, h: 100, items: [] },
      ]
    },
    { name: "Beta", w: 160, h: 120, items: [] },
    { name: "Gamma", w: 160, h: 120, items: [{id:"g1", label:"Gamma Item"}] },
  ]
};

function setDefaults(node, defaultW = 160, defaultH = 120) {
  if (node.w == null) node.w = defaultW;
  if (node.h == null) node.h = defaultH;
  if (!Array.isArray(node.items)) node.items = [];
  if (node.children) node.children.forEach(c => setDefaults(c, defaultW, defaultH));
}

setDefaults(data);

// --- Layout setup ---
const hGap = 30, vGap = 30;
const flextree = d3.flextree()
  .nodeSize(d => [getW(d) + hGap, getH(d) + vGap]);

const root = flextree.hierarchy(data);
flextree(root);

// --- SVG + groups ---
const svg = d3.select("#svg");
const gLinks = svg.append("g").attr("class", "links");
const gNodes = svg.append("g").attr("class", "nodes");

svg.call(d3.zoom().on("zoom", ev => {
  gNodes.attr("transform", ev.transform);
  gLinks.attr("transform", ev.transform);
})).call(d3.zoom().transform, d3.zoomIdentity.translate(80,80));

// --- Helpers ---
function getW(d){ return (d.data && typeof d.data.w==="number") ? d.data.w : 160; }
function getH(d){ return (d.data && typeof d.data.h==="number") ? d.data.h : 120; }
function clamp(v,a,b){ return Math.max(a, Math.min(b,v)); }

// --- Path generator ---
function elbow(d) {
  const sx = d.source.x + getW(d.source) / 2;
  const sy = d.source.y + getH(d.source);
  const tx = d.target.x + getW(d.target) / 2;
  const...