From 585a38aa921783d78dd8aeb55a173a0ad3b9395b Mon Sep 17 00:00:00 2001 From: Emily KL <4672118+emilykl@users.noreply.github.com> Date: Mon, 8 Dec 2025 16:39:42 -0500 Subject: [PATCH 1/4] fix issue where some scatter traces would lose fill after series of hide/show operations in legend --- src/traces/scatter/plot.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/traces/scatter/plot.js b/src/traces/scatter/plot.js index f22a75fbfd5..66abb9a015e 100644 --- a/src/traces/scatter/plot.js +++ b/src/traces/scatter/plot.js @@ -83,6 +83,9 @@ function createFills(gd, traceJoin, plotinfo) { var trace = d[0].trace; + trace._ownFill = null; + trace._nextFill = null; + var fillData = []; if(trace._ownfill) fillData.push('_ownFill'); if(trace._nexttrace) fillData.push('_nextFill'); @@ -91,9 +94,7 @@ function createFills(gd, traceJoin, plotinfo) { fillJoin.enter().append('g'); - fillJoin.exit() - .each(function(d) { trace[d] = null; }) - .remove(); + fillJoin.exit().remove(); fillJoin.order().each(function(d) { // make a path element inside the fill group, just so From 2a24c58417b2158087408b6b7fbfd4fe7d0c68c9 Mon Sep 17 00:00:00 2001 From: Emily KL <4672118+emilykl@users.noreply.github.com> Date: Mon, 8 Dec 2025 16:45:46 -0500 Subject: [PATCH 2/4] add jasmine test --- test/jasmine/tests/scatter_test.js | 44 ++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/test/jasmine/tests/scatter_test.js b/test/jasmine/tests/scatter_test.js index 8a3739d0d69..4c27d0a9bb8 100644 --- a/test/jasmine/tests/scatter_test.js +++ b/test/jasmine/tests/scatter_test.js @@ -1361,6 +1361,50 @@ describe('stacked area', function() { }) .then(done, done.fail); }); + + it('maintains correct fill elements when toggling trace visibility in stacked area charts', function(done) { + // Regression test for issue #7660 + // When isolating, then hiding all, then showing all traces in a stacked area chart, + // fill elements should be correctly drawn for all traces. + + function countNonEmptyFills() { + return d3SelectAll('.scatterlayer .js-fill').filter(function() { + var d = d3Select(this).attr('d'); + return d && d !== 'M0,0Z'; + }).size(); + } + + Plotly.newPlot(gd, [ + {x: [1, 2, 3], y: [2, 1, 4], stackgroup: 'one', name: 'trace 0'}, + {x: [1, 2, 3], y: [1, 1, 2], stackgroup: 'one', name: 'trace 1'}, + {x: [1, 2, 3], y: [3, 0, 2], stackgroup: 'one', name: 'trace 2'} + ]) + .then(function() { + // Initially all 3 traces should be visible with fills + expect(countNonEmptyFills()).toBe(3, 'should have 3 fill paths initially'); + + // Show trace 1 only + return Plotly.restyle(gd, 'visible', ['legendonly', true, 'legendonly']); + }) + .then(function() { + // Verify only one fill is drawn (trace 1) + expect(countNonEmptyFills()).toBe(1, 'should have 1 fill path when isolating trace 1'); + // Hide all traces + return Plotly.restyle(gd, 'visible', ['legendonly', 'legendonly', 'legendonly']); + }) + .then(function() { + // Verify no fills are drawn + expect(countNonEmptyFills()).toBe(0, 'should have 0 fill paths when hiding all traces'); + // Show all traces again + return Plotly.restyle(gd, 'visible', [true, true, true]); + }) + .then(function() { + // Verify all 3 fills are drawn again + // This is the step that was failing in #7660 + expect(countNonEmptyFills()).toBe(3, 'should have 3 fill paths after showing all traces again'); + }) + .then(done, done.fail); + }); }); describe('scatter hoverPoints', function() { From ebbbe3821ec70cf6e7f0dbe8fe149f7ea8d94350 Mon Sep 17 00:00:00 2001 From: Emily KL <4672118+emilykl@users.noreply.github.com> Date: Tue, 27 Jan 2026 11:46:29 -0500 Subject: [PATCH 3/4] add explanatory comment --- src/traces/scatter/plot.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/traces/scatter/plot.js b/src/traces/scatter/plot.js index 66abb9a015e..3c9e19df936 100644 --- a/src/traces/scatter/plot.js +++ b/src/traces/scatter/plot.js @@ -83,6 +83,11 @@ function createFills(gd, traceJoin, plotinfo) { var trace = d[0].trace; + // trace._ownFill and trace._nextFill may have leftover values + // from a previous call to createFills. They should always start as null. + // We clear both values in order to start with a clean slate. + // Note that these are DIFFERENT VARIABLES than + // trace._ownfill and trace._nexttrace referenced a few lines down. trace._ownFill = null; trace._nextFill = null; From 0cd58d14445e30470d5b145bc836a28de00b7c1f Mon Sep 17 00:00:00 2001 From: Emily KL <4672118+emilykl@users.noreply.github.com> Date: Tue, 27 Jan 2026 11:50:55 -0500 Subject: [PATCH 4/4] add draftlog --- draftlogs/7668_fix.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 draftlogs/7668_fix.md diff --git a/draftlogs/7668_fix.md b/draftlogs/7668_fix.md new file mode 100644 index 00000000000..7af1a8dc2ed --- /dev/null +++ b/draftlogs/7668_fix.md @@ -0,0 +1 @@ + - Fix issue where some traces in stacked area charts were not rendering their fill correctly after certain sequences of hide/show operations in the legend [[#7668](https://github.com/plotly/plotly.js/pull/7668)] \ No newline at end of file