Node and Link Ordering

By default ApexSankey computes node positions automatically to minimize edge crossings. When you need a specific vertical order, for example to keep a consistent narrative from top to bottom, supply an explicit order array in the data's options field.

The order array

order is a three-level nested array passed inside data.options:

  • The outer array is one entry per column (rank), left to right.
  • Each column contains one or more groups.
  • Each group is an array of node IDs, listed top to bottom.
const data = {
  nodes: [
    { id: 'LinkedIn',     title: 'LinkedIn' },
    { id: 'Indeed',       title: 'Indeed' },
    { id: 'Referral',     title: 'Referral' },
    { id: 'Applied',      title: 'Applied' },
    { id: 'Responded',    title: 'Responded' },
    { id: 'No Response',  title: 'No Response' },
    { id: 'Interviewed',  title: 'Interviewed' },
    { id: 'Rejected',     title: 'Rejected' },
    { id: 'Accepted',     title: 'Accepted' },
  ],
  edges: [
    { source: 'LinkedIn',    target: 'Applied',     value: 85, type: 'src' },
    { source: 'Indeed',      target: 'Applied',     value: 62, type: 'src' },
    { source: 'Referral',    target: 'Applied',     value: 28, type: 'src' },
    { source: 'Applied',     target: 'Responded',   value: 70, type: 'stage' },
    { source: 'Applied',     target: 'No Response',  value: 105, type: 'stage' },
    { source: 'Responded',   target: 'Interviewed', value: 22, type: 'stage' },
    { source: 'Responded',   target: 'Rejected',    value: 48, type: 'stage' },
    { source: 'Interviewed', target: 'Accepted',    value: 22, type: 'stage' },
  ],
  options: {
    order: [
      [['LinkedIn', 'Indeed', 'Referral']],   // column 0: three source nodes
      [['Applied']],                           // column 1
      [['Responded'], ['No Response']],        // column 2: two groups
      [['Interviewed'], ['Rejected']],         // column 3
      [['Accepted']],                          // column 4
    ],
  },
}

const sankey = new ApexSankey(document.getElementById('chart'), {})
sankey.render(data)

How columns map to ranks

Each top-level entry corresponds to a column in the diagram. The first entry is the leftmost column; the last is the rightmost. Every node must appear exactly once across the array, in the column that matches its position in the flow.

options: {
  order: [
    // column 0 (sources)
    [['A', 'B', 'C']],
    // column 1 (middle)
    [['D']],
    // column 2 (targets)
    [['E', 'F']],
  ],
}

Grouping within a column

Within a column, splitting nodes into separate groups (separate inner arrays) lets you cluster related nodes and control spacing between clusters. A single group keeps nodes tightly ordered; multiple groups introduce visual separation:

options: {
  order: [
    [['source1', 'source2']],

    // two distinct groups in this column — rendered with a visual gap
    [
      ['success_path_a', 'success_path_b'],
      ['failure_path'],
    ],
  ],
}

When to use explicit ordering

  • Funnels and pipelines where the top-to-bottom order tells a story (e.g. lead → applied → interviewed → hired).
  • Comparisons where you want the same category to stay in the same vertical position across columns.
  • Stable layouts across data updates, so nodes don't jump position when values change.

When order is omitted, ApexSankey falls back to its automatic crossing-minimization layout.

Keeping order stable across updates

Because the automatic layout can reposition nodes when values change, supplying order is the reliable way to keep a fixed arrangement across re-renders. Recompute or reuse the same order array whenever you call render() with new data:

const order = [
  [['LinkedIn', 'Indeed', 'Referral']],
  [['Applied']],
  [['Responded'], ['No Response']],
  [['Interviewed'], ['Rejected']],
  [['Accepted']],
]

function draw(nodes, edges) {
  sankey.render({ nodes, edges, options: { order } })
}

React example

import { ApexSankey } from 'react-apexsankey'

const data = {
  nodes: [
    { id: 'a', title: 'A' },
    { id: 'b', title: 'B' },
    { id: 'c', title: 'C' },
    { id: 'd', title: 'D' },
  ],
  edges: [
    { source: 'a', target: 'c', value: 20, type: 'flow' },
    { source: 'b', target: 'c', value: 15, type: 'flow' },
    { source: 'c', target: 'd', value: 35, type: 'flow' },
  ],
  options: {
    order: [
      [['a', 'b']],
      [['c']],
      [['d']],
    ],
  },
}

export default function OrderedSankey() {
  return <ApexSankey data={data} options={{ nodeWidth: 20 }} />
}

Note: in the data object, options holds the layout order; visual options like nodeWidth go in the component's options prop (or the constructor options in vanilla JS).