From dd4765eaf80d483bb0c134db1835a25483cb8aeb Mon Sep 17 00:00:00 2001 From: Michael Potter Date: Wed, 10 Jan 2024 15:35:05 -0800 Subject: [PATCH 1/8] add a link hovercolor attribute so that end users can customize their hover styling easily (+6 squashed commits) Squashed commits: [9555c0c06] catch exceptions when trying to read access-restricted css files, and update test case to look for css styling [635e5ee64] adhere to style guide CI/CD feedback [afcbcc23a] remove 'const' in favor of 'var' per CI/CD rules [5e2444bca] use 'var' instead of 'let' per ci/cd guide [ba96e96f9] add a draftlogs entry [b8238e0f6] Allow end users to override the sankey link hover style by providing their own css styling --- draftlogs/6839_change.md | 1 + src/traces/sankey/attributes.js | 9 +++++++++ src/traces/sankey/calc.js | 2 ++ src/traces/sankey/defaults.js | 5 +++++ src/traces/sankey/plot.js | 25 +++++++++++++++++++------ src/traces/sankey/render.js | 3 +++ test/jasmine/tests/sankey_test.js | 2 +- 7 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 draftlogs/6839_change.md diff --git a/draftlogs/6839_change.md b/draftlogs/6839_change.md new file mode 100644 index 00000000000..6fe959ed85d --- /dev/null +++ b/draftlogs/6839_change.md @@ -0,0 +1 @@ +- Update Sankey trace to allow user-defined link hover style override [[#6839](https://github.com/plotly/plotly.js/pull/6839)] \ No newline at end of file diff --git a/src/traces/sankey/attributes.js b/src/traces/sankey/attributes.js index e792a3b3234..dd7ed768eb7 100644 --- a/src/traces/sankey/attributes.js +++ b/src/traces/sankey/attributes.js @@ -195,6 +195,15 @@ var attrs = module.exports = overrideAll({ 'If `link.color` is omitted, then by default, a translucent grey link will be used.' ].join(' ') }, + hovercolor: { + valType: 'color', + arrayOk: true, + description: [ + 'Sets the `link` hover color. It can be a single value, or an array for specifying hovor colors for', + 'each `link`. If `link.hovercolor` is omitted, then by default, links will become solid grey when', + 'hovered over.' + ].join(' ') + }, customdata: { valType: 'data_array', editType: 'calc', diff --git a/src/traces/sankey/calc.js b/src/traces/sankey/calc.js index 4cbb93c1fdb..1be532a5c00 100644 --- a/src/traces/sankey/calc.js +++ b/src/traces/sankey/calc.js @@ -14,6 +14,7 @@ function convertToD3Sankey(trace) { var links = []; var hasLinkColorArray = isArrayOrTypedArray(linkSpec.color); + var hasLinkHoverColorArray = isArrayOrTypedArray(linkSpec.hovercolor); var hasLinkCustomdataArray = isArrayOrTypedArray(linkSpec.customdata); var linkedNodes = {}; @@ -96,6 +97,7 @@ function convertToD3Sankey(trace) { pointNumber: i, label: label, color: hasLinkColorArray ? linkSpec.color[i] : linkSpec.color, + hovercolor: hasLinkHoverColorArray ? linkSpec.hovercolor[i] : linkSpec.hovercolor, customdata: hasLinkCustomdataArray ? linkSpec.customdata[i] : linkSpec.customdata, concentrationscale: concentrationscale, source: source, diff --git a/src/traces/sankey/defaults.js b/src/traces/sankey/defaults.js index 3b8780f376e..d480895cca7 100644 --- a/src/traces/sankey/defaults.js +++ b/src/traces/sankey/defaults.js @@ -67,7 +67,12 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout 'rgba(255, 255, 255, 0.6)' : 'rgba(0, 0, 0, 0.2)'; + var defaultHoverColor = tinycolor(layout.paper_bgcolor).getLuminance() < 0.333 ? + 'rgba(128, 128, 128, 1.0)' : + 'rgba(128, 128, 128, 1.0)'; + coerceLink('color', Lib.repeat(defaultLinkColor, linkOut.value.length)); + coerceLink('hovercolor', Lib.repeat(defaultHoverColor, linkOut.value.length)); coerceLink('customdata'); handleArrayContainerDefaults(linkIn, linkOut, { diff --git a/src/traces/sankey/plot.js b/src/traces/sankey/plot.js index 8907d1fc02f..57857d3fc07 100644 --- a/src/traces/sankey/plot.js +++ b/src/traces/sankey/plot.js @@ -62,9 +62,13 @@ function nodeNonHoveredStyle(sankeyNode, d, sankey) { } function linkHoveredStyle(d, sankey, visitNodes, sankeyLink) { - sankeyLink.style('fill-opacity', function(l) { + sankeyLink.style('fill', function(l) { if(!l.link.concentrationscale) { - return 0.4; + return l.tinyColorHoverHue; + } + }).style('fill-opacity', function(l) { + if(!l.link.concentrationscale) { + return l.tinyColorHoverAlpha; } }); @@ -74,9 +78,13 @@ function linkHoveredStyle(d, sankey, visitNodes, sankeyLink) { ownTrace(sankey, d) .selectAll('.' + cn.sankeyLink) .filter(function(l) {return l.link.label === label;}) - .style('fill-opacity', function(l) { + .style('fill', function(l) { if(!l.link.concentrationscale) { - return 0.4; + return l.tinyColorHoverHue; + } + }).style('fill-opacity', function(l) { + if(!l.link.concentrationscale) { + return l.tinyColorHoverAlpha; } }); } @@ -91,7 +99,11 @@ function linkHoveredStyle(d, sankey, visitNodes, sankeyLink) { } function linkNonHoveredStyle(d, sankey, visitNodes, sankeyLink) { - sankeyLink.style('fill-opacity', function(d) {return d.tinyColorAlpha;}); + sankeyLink.style('fill', function(l) { + return l.tinyColorHue; + }).style('fill-opacity', function(l) { + return l.tinyColorAlpha; + }); sankeyLink.each(function(curLink) { var label = curLink.link.label; @@ -99,7 +111,8 @@ function linkNonHoveredStyle(d, sankey, visitNodes, sankeyLink) { ownTrace(sankey, d) .selectAll('.' + cn.sankeyLink) .filter(function(l) {return l.link.label === label;}) - .style('fill-opacity', function(d) {return d.tinyColorAlpha;}); + .style('fill', function(l) {return l.tinyColorHue;}) + .style('fill-opacity', function(l) {return l.tinyColorAlpha;}); } }); diff --git a/src/traces/sankey/render.js b/src/traces/sankey/render.js index 0894b058c27..2b0651f0e2f 100644 --- a/src/traces/sankey/render.js +++ b/src/traces/sankey/render.js @@ -299,6 +299,7 @@ function sankeyModel(layout, d, traceIndex) { function linkModel(d, l, i) { var tc = tinycolor(l.color); + var htc = tinycolor(l.hovercolor); var basicKey = l.source.label + '|' + l.target.label; var key = basicKey + '__' + i; @@ -314,6 +315,8 @@ function linkModel(d, l, i) { link: l, tinyColorHue: Color.tinyRGB(tc), tinyColorAlpha: tc.getAlpha(), + tinyColorHoverHue: Color.tinyRGB(htc), + tinyColorHoverAlpha: htc.getAlpha(), linkPath: linkPath, linkLineColor: d.linkLineColor, linkLineWidth: d.linkLineWidth, diff --git a/test/jasmine/tests/sankey_test.js b/test/jasmine/tests/sankey_test.js index 18506de1eee..b47db4cb27e 100644 --- a/test/jasmine/tests/sankey_test.js +++ b/test/jasmine/tests/sankey_test.js @@ -1087,7 +1087,7 @@ describe('sankey tests', function() { .filter(function(obj) { return obj.link.label === 'stream 1'; })[0].forEach(function(l) { - expect(l.style.fillOpacity).toEqual('0.4'); + expect(l.style.fillOpacity).toEqual('1.0'); }); }).then(function() { mouseEvent('mouseout', 200, 250); From ecfc8b99023ac0b624f40d305013ec9b121c11ed Mon Sep 17 00:00:00 2001 From: Michael Potter Date: Mon, 22 Jan 2024 12:45:42 -0800 Subject: [PATCH 2/8] update draftlogs --- draftlogs/{6839_change.md => 6864_change.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename draftlogs/{6839_change.md => 6864_change.md} (50%) diff --git a/draftlogs/6839_change.md b/draftlogs/6864_change.md similarity index 50% rename from draftlogs/6839_change.md rename to draftlogs/6864_change.md index 6fe959ed85d..ae345b8623f 100644 --- a/draftlogs/6839_change.md +++ b/draftlogs/6864_change.md @@ -1 +1 @@ -- Update Sankey trace to allow user-defined link hover style override [[#6839](https://github.com/plotly/plotly.js/pull/6839)] \ No newline at end of file +- Update Sankey trace to allow user-defined link hover style override [[#6864](https://github.com/plotly/plotly.js/pull/6864)] \ No newline at end of file From 2b0f2ae1c30bde330fe1ce45a1b9aaf2c15df899 Mon Sep 17 00:00:00 2001 From: Michael Potter Date: Mon, 22 Jan 2024 13:05:23 -0800 Subject: [PATCH 3/8] switch test to account for round-off --- test/jasmine/tests/sankey_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jasmine/tests/sankey_test.js b/test/jasmine/tests/sankey_test.js index b47db4cb27e..3e0d5558a4c 100644 --- a/test/jasmine/tests/sankey_test.js +++ b/test/jasmine/tests/sankey_test.js @@ -1087,7 +1087,7 @@ describe('sankey tests', function() { .filter(function(obj) { return obj.link.label === 'stream 1'; })[0].forEach(function(l) { - expect(l.style.fillOpacity).toEqual('1.0'); + expect(l.style.fillOpacity).toEqual('1'); }); }).then(function() { mouseEvent('mouseout', 200, 250); From 1055a02a78eaf79e227a591a39f57da6d80c21f9 Mon Sep 17 00:00:00 2001 From: Michael Potter Date: Mon, 22 Jan 2024 13:25:35 -0800 Subject: [PATCH 4/8] update plot-schema to account for hovercolor entry --- test/plot-schema.json | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/plot-schema.json b/test/plot-schema.json index 9f5b82beb8a..94d9cfa4e4b 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -44148,6 +44148,17 @@ }, "description": "The links of the Sankey plot.", "editType": "calc", + "hovercolor": { + "arrayOk": true, + "description": "Sets the `link` hover color. It can be a single value, or an array for specifying hovor colors for each `link`. If `link.hovercolor` is omitted, then by default, links will become solid grey when hovered over.", + "editType": "calc", + "valType": "color" + }, + "hovercolorsrc": { + "description": "Sets the source reference on Chart Studio Cloud for `hovercolor`.", + "editType": "none", + "valType": "string" + }, "hoverinfo": { "description": "Determines which trace information appear when hovering links. If `none` or `skip` are set, no information is displayed upon hovering. But, if `none` is set, click and hover events are still fired.", "dflt": "all", From 82315aa8110fcea92fcacf62a2eacda78b648d31 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi <33888540+archmoj@users.noreply.github.com> Date: Fri, 26 Jan 2024 16:31:06 -0500 Subject: [PATCH 5/8] Update src/traces/sankey/attributes.js --- src/traces/sankey/attributes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/traces/sankey/attributes.js b/src/traces/sankey/attributes.js index dd7ed768eb7..beebe9c8465 100644 --- a/src/traces/sankey/attributes.js +++ b/src/traces/sankey/attributes.js @@ -199,7 +199,7 @@ var attrs = module.exports = overrideAll({ valType: 'color', arrayOk: true, description: [ - 'Sets the `link` hover color. It can be a single value, or an array for specifying hovor colors for', + 'Sets the `link` hover color. It can be a single value, or an array for specifying hover colors for', 'each `link`. If `link.hovercolor` is omitted, then by default, links will become solid grey when', 'hovered over.' ].join(' ') From 52583d2895be106702faee496f964c959ae59e1d Mon Sep 17 00:00:00 2001 From: Michael Potter Date: Fri, 26 Jan 2024 14:43:50 -0800 Subject: [PATCH 6/8] spelling fix --- test/plot-schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/plot-schema.json b/test/plot-schema.json index 94d9cfa4e4b..902d0f843df 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -44150,7 +44150,7 @@ "editType": "calc", "hovercolor": { "arrayOk": true, - "description": "Sets the `link` hover color. It can be a single value, or an array for specifying hovor colors for each `link`. If `link.hovercolor` is omitted, then by default, links will become solid grey when hovered over.", + "description": "Sets the `link` hover color. It can be a single value, or an array for specifying hover colors for each `link`. If `link.hovercolor` is omitted, then by default, links will become solid grey when hovered over.", "editType": "calc", "valType": "color" }, From 58bb631d7f222a0019df795ea62337ddcdf54d67 Mon Sep 17 00:00:00 2001 From: Michael Potter Date: Tue, 30 Jan 2024 15:14:14 -0800 Subject: [PATCH 7/8] modify hover default to change opacity rather than set everything to grey --- src/traces/sankey/attributes.js | 4 ++-- src/traces/sankey/defaults.js | 31 +++++++++++++++++++++++-------- test/jasmine/tests/sankey_test.js | 2 +- test/plot-schema.json | 2 +- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/traces/sankey/attributes.js b/src/traces/sankey/attributes.js index beebe9c8465..3334a8a87d3 100644 --- a/src/traces/sankey/attributes.js +++ b/src/traces/sankey/attributes.js @@ -200,8 +200,8 @@ var attrs = module.exports = overrideAll({ arrayOk: true, description: [ 'Sets the `link` hover color. It can be a single value, or an array for specifying hover colors for', - 'each `link`. If `link.hovercolor` is omitted, then by default, links will become solid grey when', - 'hovered over.' + 'each `link`. If `link.hovercolor` is omitted, then by default, links will become slightly more', + 'opaque when hovered over.' ].join(' ') }, customdata: { diff --git a/src/traces/sankey/defaults.js b/src/traces/sankey/defaults.js index d480895cca7..704d1eb40e6 100644 --- a/src/traces/sankey/defaults.js +++ b/src/traces/sankey/defaults.js @@ -63,16 +63,31 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout handleHoverLabelDefaults(linkIn, linkOut, coerceLink, hoverlabelDefault); coerceLink('hovertemplate'); - var defaultLinkColor = tinycolor(layout.paper_bgcolor).getLuminance() < 0.333 ? - 'rgba(255, 255, 255, 0.6)' : - 'rgba(0, 0, 0, 0.2)'; + var darkBG = tinycolor(layout.paper_bgcolor).getLuminance() < 0.333; + var defaultLinkColor = darkBG ? 'rgba(255, 255, 255, 0.6)' : 'rgba(0, 0, 0, 0.2)'; + var linkColor = coerceLink('color', defaultLinkColor); + + function makeDefaultHoverColor(_linkColor) { + var tc = tinycolor(_linkColor); + if (!tc.isValid()) { + // hopefully the user-specified color is valid, but if not that can be caught elsewhere + return _linkColor; + } + var alpha = tc.getAlpha(); + if (alpha <= 0.8) { + tc.setAlpha(alpha + 0.2); + } + else { + tc = darkBG ? tc.brighten() : tc.darken(); + } + return tc.toRgbString(); + } - var defaultHoverColor = tinycolor(layout.paper_bgcolor).getLuminance() < 0.333 ? - 'rgba(128, 128, 128, 1.0)' : - 'rgba(128, 128, 128, 1.0)'; + coerceLink('hovercolor', Array.isArray(linkColor) ? + linkColor.map(makeDefaultHoverColor) : + makeDefaultHoverColor(linkColor) + ); - coerceLink('color', Lib.repeat(defaultLinkColor, linkOut.value.length)); - coerceLink('hovercolor', Lib.repeat(defaultHoverColor, linkOut.value.length)); coerceLink('customdata'); handleArrayContainerDefaults(linkIn, linkOut, { diff --git a/test/jasmine/tests/sankey_test.js b/test/jasmine/tests/sankey_test.js index 3e0d5558a4c..18506de1eee 100644 --- a/test/jasmine/tests/sankey_test.js +++ b/test/jasmine/tests/sankey_test.js @@ -1087,7 +1087,7 @@ describe('sankey tests', function() { .filter(function(obj) { return obj.link.label === 'stream 1'; })[0].forEach(function(l) { - expect(l.style.fillOpacity).toEqual('1'); + expect(l.style.fillOpacity).toEqual('0.4'); }); }).then(function() { mouseEvent('mouseout', 200, 250); diff --git a/test/plot-schema.json b/test/plot-schema.json index 902d0f843df..e23caec43f2 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -44150,7 +44150,7 @@ "editType": "calc", "hovercolor": { "arrayOk": true, - "description": "Sets the `link` hover color. It can be a single value, or an array for specifying hover colors for each `link`. If `link.hovercolor` is omitted, then by default, links will become solid grey when hovered over.", + "description": "Sets the `link` hover color. It can be a single value, or an array for specifying hover colors for each `link`. If `link.hovercolor` is omitted, then by default, links will become slightly more opaque when hovered over.", "editType": "calc", "valType": "color" }, From 2c7eda15abafd47dc661826caf7e2d27111cf2e1 Mon Sep 17 00:00:00 2001 From: Michael Potter Date: Tue, 30 Jan 2024 15:28:18 -0800 Subject: [PATCH 8/8] fix linter issues --- src/traces/sankey/defaults.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/traces/sankey/defaults.js b/src/traces/sankey/defaults.js index 704d1eb40e6..a403dbf762d 100644 --- a/src/traces/sankey/defaults.js +++ b/src/traces/sankey/defaults.js @@ -69,21 +69,20 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout function makeDefaultHoverColor(_linkColor) { var tc = tinycolor(_linkColor); - if (!tc.isValid()) { + if(!tc.isValid()) { // hopefully the user-specified color is valid, but if not that can be caught elsewhere return _linkColor; } var alpha = tc.getAlpha(); - if (alpha <= 0.8) { + if(alpha <= 0.8) { tc.setAlpha(alpha + 0.2); - } - else { + } else { tc = darkBG ? tc.brighten() : tc.darken(); } return tc.toRgbString(); } - coerceLink('hovercolor', Array.isArray(linkColor) ? + coerceLink('hovercolor', Array.isArray(linkColor) ? linkColor.map(makeDefaultHoverColor) : makeDefaultHoverColor(linkColor) );