You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
At the moment Sankey nodes display their labels as text, but for the links one can only have text on hover. It would be great to have an option to display text inside (or just above) the links.
Related issue: add optional text to histogram and to heatmap traces (which would remove the need for annotated heatmap figure factory).
Reacted by Kenan, UFO-101, Philip Leicester, FC Esja, Alex Rudd, Kajetan Sygula, Hannah Giovanna Dawson, ccpDaniel, Iylia Hutta, ndrwrbgs and 2 more
OK a Sankey is a visualisation tool, but come on, seeing the magnitude of the pipes in a png export is like, why wouldn't you make this doable! Sorry to gripe; but other Sankey tools are pants and so plotly's offer is a last gasp saloon.
I can see that there is a label attribute for link, but adding labels to it does nothing. And agreed being able to specify texttemplate would also be great.
Reacted by Kajetan Sygula, Hannah Giovanna Dawson, Hooper, ccpDaniel and Iylia Hutta
I would be willing to work on a PR for this, if there is interest.
Motivation
Sankey links currently expose their information (name via link.label, plus value) only through the hover tooltip. There is no way to display link text permanently on the diagram, the way node labels are always drawn. This forces users to either accept hover-only interaction (useless for static export/PNG/print) or build fragile client-side SVG overlays.
There is some community interest in exactly this - see this issue.
Implementation options
Option A — reuse link.label as the on/off switch
Render link.label when it is set.
This would need no new attributes, however one would only be able to show the label string, no value or custom text. It would also silently change behavior for existing figures that set link.label purely for hover - i.e. not backward compatible.
Option B — introduce link.textinfo
A flaglist string: any combination of "label", "value" or other flags joined with "+", or "none".
Pro: explicit opt-in (default "none" → no behavior change); users choose which pieces of information to show; consistent with the textinfo pattern already established in traces such as funnel and pie, so the attribute semantics are familiar to users and reusable in code.
Con: fixed formatting/ordering; no full control over the rendered string.
Option C — link.textinfo (as in B) plus link.texttemplate
texttemplate is a string or array of strings: a template for the rendered text (e.g. "%{label}: %{value}"), overriding textinfo when set; supports the same variables as the link hovertemplate (value, label, source, target, customdata, …).
Pro: full control, per-link templating, and still a clean opt-in. The textinfo + texttemplate duo is exactly the pattern funnel and pie already implement (see pie.texttemplate and funnel.texttemplate), so we can follow — and largely reuse — their template machinery rather than inventing anything new.
Con: the most code (template parsing, array handling), but reuses existing template machinery.
Backward compatibility
Option A: not backward compatible — existing figures that set link.label for hover would suddenly render on-diagram text.
Options B/C: fully backward compatible. New attributes default to textinfo: "none" (and texttemplate: ""), so existing figures render identically; link text is strictly opt-in. No changes to node labels, hover, or existing baselines.
Key implementation points
Render one <text> per link inside the .sankey group at the link midpoint ((source.x1 + target.x0) / 2, (y0 + y1) / 2), so the existing group-level orientation transform applies.
Apply the same counter-transform as node labels (flipText) so text stays upright in all orientations (h/v).
Reposition the labels in updateShapes so they follow live node drags (the underlying y0/y1 are already recomputed there).
For circular links the analytic midpoint is inaccurate; use path.getPointAtLength(totalLength / 2) for a robust anchor.
Respect a new link.textfont (mirroring node/trace textfont) and valueformat/valuesuffix for the value component.
Activity
antoinerg commentedon Apr 9, 2020
Do you have any suggestions about how the users would specify this? Do we need a new attribute?
cc @nicolaskruchten
emmanuelle commentedon Apr 9, 2020
maybe just a
texttemplatewhich would be empty by default? And/ortextinfoas inpieorfunnel?kenakofer commentedon Nov 10, 2022
Yes please. It's strange that in the case of Sankey links, specifying a label is actually just specifying a hovertemplate.
wattcommunity commentedon Apr 22, 2024
OK a Sankey is a visualisation tool, but come on, seeing the magnitude of the pipes in a png export is like, why wouldn't you make this doable! Sorry to gripe; but other Sankey tools are pants and so plotly's offer is a last gasp saloon.
fc-esja commentedon Apr 24, 2024
I can see that there is a
labelattribute forlink, but adding labels to it does nothing. And agreed being able to specifytexttemplatewould also be great.[-][FEAT] Optional text on Sankey links[/-][+]add optional text on Sankey links[/+]iyliahutta commentedon Sep 5, 2024
is this in development or will be anytime soon? would really love to have this feature and i doubt i'm the only one.
juanyaohuang commentedon May 25, 2025
I create a piece of js code to permanently add link values, I tested it in R Shiny it works great:
htmlwidgets::onRender(x=p, jsCode='
function(el) {
//reference code: https://stackoverflow.com/questions/67291003/add-text-to-svg-path-dynamically
//reference code: https://stackoverflow.com/questions/9281199/adding-text-to-svg-document-in-javascript
//reference code: https://stackoverflow.com/questions/52335837/event-when-clicking-a-name-in-the-legend-of-a-plotlys-graph-in-r-shiny
//reference code: https://stackoverflow.com/questions/42280913/troubleshoot-javascript-code-in-onrender-function-of-htmlwidgets
function addLabelText(bgPath, labelText) {
let bbox = bgPath.getBBox();
let x = bbox.x + bbox.width / 2;
let y = bbox.y + bbox.height / 2;
}')
fstricker commentedon Nov 11, 2025
Is there any news on this issue? I find it strange that there is no way of showing persistent link texts regardless of hover states.
wf-r commentedon Jul 2, 2026
I would be willing to work on a PR for this, if there is interest.
Motivation
Sankey links currently expose their information (name via
link.label, plus value) only through the hover tooltip. There is no way to display link text permanently on the diagram, the way node labels are always drawn. This forces users to either accept hover-only interaction (useless for static export/PNG/print) or build fragile client-side SVG overlays.There is some community interest in exactly this - see this issue.
Implementation options
Option A — reuse
link.labelas the on/off switchRender
link.labelwhen it is set.This would need no new attributes, however one would only be able to show the label string, no value or custom text. It would also silently change behavior for existing figures that set
link.labelpurely for hover - i.e. not backward compatible.Option B — introduce
link.textinfoA flaglist string: any combination of
"label","value"or other flags joined with"+", or"none"."none"→ no behavior change); users choose which pieces of information to show; consistent with thetextinfopattern already established in traces such asfunnelandpie, so the attribute semantics are familiar to users and reusable in code.Option C —
link.textinfo(as in B) pluslink.texttemplatetexttemplateis a string or array of strings: a template for the rendered text (e.g."%{label}: %{value}"), overridingtextinfowhen set; supports the same variables as the linkhovertemplate(value,label,source,target,customdata, …).textinfo+texttemplateduo is exactly the patternfunnelandpiealready implement (seepie.texttemplateandfunnel.texttemplate), so we can follow — and largely reuse — their template machinery rather than inventing anything new.Backward compatibility
link.labelfor hover would suddenly render on-diagram text.textinfo: "none"(andtexttemplate: ""), so existing figures render identically; link text is strictly opt-in. No changes to node labels, hover, or existing baselines.Key implementation points
<text>per link inside the.sankeygroup at the link midpoint ((source.x1 + target.x0) / 2,(y0 + y1) / 2), so the existing group-level orientation transform applies.flipText) so text stays upright in all orientations (h/v).updateShapesso they follow live node drags (the underlyingy0/y1are already recomputed there).path.getPointAtLength(totalLength / 2)for a robust anchor.link.textfont(mirroringnode/tracetextfont) andvalueformat/valuesuffixfor the value component.wf-r commentedon Jul 2, 2026
An example for link labels with
link.textinfoandlink.texttemplatewould be this:An example for the configuration with
link.valueformat,link.valuesuffixandlink.textfontwould be this:robertclaus commentedon Aug 4, 2026
Thanks for the PR @wf-r ! @camdecoster had a chance to review if you are still looking into this!