React ApexSankey

Installation

npm install react-apexsankey apexsankey @svgdotjs/svg.js

Or with yarn:

yarn add react-apexsankey apexsankey @svgdotjs/svg.js

Demo

View Demo Project created using react-apexsankey

Loading ApexSankey

Important: You must load ApexSankey before using the React component. Choose one of the following methods:

Option 1: ES Module Import (Recommended)

Import ApexSankey at your app's entry point to register it globally:

// main.tsx or index.tsx
import "apexsankey";
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

Option 2: CDN Script Tags

Add the scripts to your index.html before your app bundle:

<!DOCTYPE html>
<html>
  <head>
    <script src="https://cdn.jsdelivr.net/npm/@svgdotjs/svg.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/apexsankey/apexsankey.min.js"></script>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

Quick Start

import ApexSankey from "react-apexsankey";

const data = {
  nodes: [
    { id: "oil", title: "Oil" },
    { id: "gas", title: "Natural Gas" },
    { id: "coal", title: "Coal" },
    { id: "fossil", title: "Fossil Fuels" },
    { id: "energy", title: "Energy" },
  ],
  edges: [
    { source: "oil", target: "fossil", value: 15 },
    { source: "gas", target: "fossil", value: 20 },
    { source: "coal", target: "fossil", value: 25 },
    { source: "fossil", target: "energy", value: 60 },
  ],
};

function App() {
  return (
    <ApexSankey
      data={data}
      options={{
        width: 800,
        height: 600,
        nodeWidth: 20,
      }}
    />
  );
}

License Setup

If you have a commercial license, set it once at app initialization before rendering any charts:

import { setApexSankeyLicense } from "react-apexsankey";

// call this at the top of your app
setApexSankeyLicense("your-license-key-here");

Example with React app entry point:

// main.tsx or index.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import { setApexSankeyLicense } from "react-apexsankey";
import App from "./App";

// set license before rendering
setApexSankeyLicense("your-license-key-here");

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

Using Refs

Access the underlying SankeyGraph instance via refs:

import { useRef, useEffect } from "react";
import ApexSankey, { ApexSankeyRef } from "react-apexsankey";

function App() {
  const chartRef = useRef<ApexSankeyRef>(null);

  useEffect(() => {
    if (chartRef.current?.graph) {
      console.log("Graph instance:", chartRef.current.graph);
      console.log("Max rank:", chartRef.current.graph.maxRank);
    }
  }, []);

  return <ApexSankey ref={chartRef} data={data} options={options} />;
}

Props

PropTypeRequiredDescription
dataGraphDataYesSankey diagram data (nodes and edges)
options{'Partial<SankeyOptions>'}NoConfiguration options for the diagram
classNamestringNoCSS class name for the container element
styleCSSPropertiesNoInline styles for the container element

Data Format

Nodes

interface Node {
  id: string; // unique identifier
  title: string; // display label
  color?: string; // optional custom color
}

Edges

interface Edge {
  source: string; // source node id
  target: string; // target node id
  value: number; // edge weight/size
  type?: string; // optional grouping type
  color?: string; // optional custom color
}

Complete Data Structure

interface GraphData {
  nodes: Node[];
  edges: Edge[];
  options?: {
    order?: string[][][]; // custom node ordering
    alignLinkTypes?: boolean; // align links by type
  };
}

Options

OptionTypeDefaultDescription
widthnumber | string800Width of graph container
heightnumber | string800Height of graph container
canvasStylestring""CSS styles for canvas root container
spacingnumber100Spacing from top and left of graph container
nodeWidthnumber20Width of graph nodes
nodeBorderWidthnumber1Border width of nodes in pixels
nodeBorderColorstring""Border color of nodes
onNodeClick(node: Node) => voidundefinedCallback function for node click
edgeOpacitynumber0.4Opacity value for edges (0 to 1)
edgeGradientFillbooleantrueEnable gradient fill based on node colors
enableTooltipbooleanfalseEnable tooltip on hover
enableToolbarbooleanfalseEnable/disable graph toolbar
tooltipIdstring"sankey-tooltip-container"Tooltip HTML element id
tooltipTemplate(content) => stringdefault templateHTML template for tooltip
tooltipBorderColorstring"#BCBCBC"Border color of tooltip
tooltipBGColorstring"#FFFFFF"Background color of tooltip
fontSizestring"14px"Font size of node labels
fontFamilystring""Font family of node labels
fontWeightstring"400"Font weight of node labels
fontColorstring"#000000"Font color of node labels

Custom Node Ordering

You can specify custom node ordering using the order option in data:

const data = {
  nodes: [
    { id: "a", title: "A" },
    { id: "b", title: "B" },
    { id: "c", title: "C" },
  ],
  edges: [
    { source: "a", target: "c", value: 1 },
    { source: "b", target: "c", value: 2 },
  ],
  options: {
    order: [
      [["a", "b"]], // first layer
      [["c"]], // second layer
    ],
  },
};

Custom Tooltip

const options = {
  enableTooltip: true,
  tooltipTemplate: ({ source, target, value }) => `
    <div style="padding: 8px;">
      <strong>${source.title}</strong> → <strong>${target.title}</strong>
      <br />
      Value: ${value}
    </div>
  `,
};

Styling

Container Styling

<ApexSankey
  data={data}
  className="my-sankey-chart"
  style={{ border: "1px solid #ccc", borderRadius: 8 }}
  options={options}
/>

Canvas Styling

const options = {
  canvasStyle: "background: #f6f6f6; border: 1px solid #caced0;",
};

TypeScript

All types are exported for use in your TypeScript projects:

import ApexSankey, {
  GraphData,
  Node,
  Edge,
  SankeyOptions,
  ApexSankeyRef,
  ApexSankeyProps,
} from "react-apexsankey";

SSR Support

This component is SSR-safe and renders an empty container on the server. The chart is only rendered client-side after hydration.