Path Highlighting and Interaction

When a user hovers a node or edge, ApexSankey can highlight the entire connected flow path and dim everything else. This makes it easy to trace where a flow comes from and where it goes in a dense diagram.

Connected-path highlighting

highlightConnectedPath is enabled by default. On hover, the connected upstream and downstream flows stay at full opacity while unrelated elements fade to dimOpacity.

OptionTypeDefaultDescription
highlightConnectedPathbooleantrueHighlight the connected flow path when hovering a node or edge
dimOpacitynumber0.15Opacity applied to unrelated (dimmed) elements while highlighting is active
const sankey = new ApexSankey(document.getElementById('chart'), {
  highlightConnectedPath: true,
  dimOpacity: 0.2,
})
sankey.render(data)

Disabling highlighting

Set highlightConnectedPath: false for a static diagram where hover has no effect:

const sankey = new ApexSankey(el, {
  highlightConnectedPath: false,
})

Tuning the dim level

Lower dimOpacity values make the highlighted path stand out more sharply against the dimmed background; higher values keep more context visible:

const sankey = new ApexSankey(el, {
  highlightConnectedPath: true,
  dimOpacity: 0.08,   // strong contrast — unrelated flows nearly vanish
})

Node click callback

onNodeClick fires when the user clicks a node. It receives a SankeyNode object describing the clicked node.

const sankey = new ApexSankey(el, {
  onNodeClick: (node) => {
    console.log('Clicked node:', node)
    console.log('Node data:', node.data)     // { id, title, color, ... }
    console.log('Flow value:', node.value)   // total value through the node
  },
})
sankey.render(data)

SankeyNode fields

FieldTypeDescription
dataNodeData | nullThe node's user data: { id, title, color, direction, forceY }
valuenumberTotal flow value passing through the node
ranknumberColumn index (0-based) of the node in the layout
x, ynumberComputed position of the node
dynumberComputed height of the node rectangle
directionstringFlow direction for the node
spaceAbove, spaceBelownumberWhitespace above/below the node

Building a drill-down interaction

Combine onNodeClick with your own state to drive a detail panel or filter:

const sankey = new ApexSankey(el, {
  highlightConnectedPath: true,
  dimOpacity: 0.15,
  onNodeClick: (node) => {
    const id = node.data?.id
    if (!id) return
    showDetailPanel(id, node.value)
  },
})
sankey.render(data)

function showDetailPanel(id, value) {
  document.getElementById('panel').innerHTML = `
    <h3>${id}</h3>
    <p>Total flow: ${value}</p>
  `
}

React example

In React, use the top-level onNodeClick prop (not options.onNodeClick, which the wrapper omits):

import { useState } from 'react'
import { ApexSankey } from 'react-apexsankey'
import type { SankeyNode } from 'react-apexsankey'

export default function InteractiveSankey() {
  const [selected, setSelected] = useState<string | null>(null)

  return (
    <div>
      {selected && <p>Selected: {selected}</p>}
      <ApexSankey
        data={data}
        options={{ highlightConnectedPath: true, dimOpacity: 0.15 }}
        onNodeClick={(node: SankeyNode) => setSelected(node.data?.id ?? null)}
      />
    </div>
  )
}

Vue example

<template>
  <div>
    <p v-if="selected">Selected: {{ selected }}</p>
    <ApexSankey :data="data" :options="options" @nodeClick="onNodeClick" />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import ApexSankey from 'vue-apexsankey'

const selected = ref<string | null>(null)
const options = { highlightConnectedPath: true, dimOpacity: 0.15 }

const onNodeClick = (node) => {
  selected.value = node.data?.id ?? null
}
</script>