diff --git a/draftlogs/7558_fix.md b/draftlogs/7558_fix.md new file mode 100644 index 00000000000..2074f5f689a --- /dev/null +++ b/draftlogs/7558_fix.md @@ -0,0 +1 @@ + - Set `cliponaxis: false` by default for bar traces with `text` and `textposition: 'auto'` or `'outside'`, to prevent text clipping [#7558](https://github.com/plotly/plotly.js/pull/7558) diff --git a/src/traces/bar/defaults.js b/src/traces/bar/defaults.js index 66cd408b06f..931f9871a76 100644 --- a/src/traces/bar/defaults.js +++ b/src/traces/bar/defaults.js @@ -148,7 +148,18 @@ function handleText(traceIn, traceOut, layout, coerce, textposition, opts) { if(moduleHasSelected) coerce('selected.textfont.color'); if(moduleHasUnselected) coerce('unselected.textfont.color'); if(moduleHasConstrain) coerce('constraintext'); - if(moduleHasCliponaxis) coerce('cliponaxis'); + if(moduleHasCliponaxis) { + if(traceOut.text && ['auto', 'outside'].includes(textposition)) { + // When `textposition` is `'outside'` (or `auto`), bar labels outside + // the bar are very frequently clipped since text is not included + // in autorange calculations. So we set `cliponaxis` to `false` by default + // in that case to prevent clipping; otherwise we use the normal default + // for `cliponaxis`, which is `true`. + coerce('cliponaxis', false); + } else { + coerce('cliponaxis'); + } + } if(moduleHasTextangle) coerce('textangle'); coerce('texttemplate'); diff --git a/src/traces/scatter/attributes.js b/src/traces/scatter/attributes.js index 84844d8fc60..4c8e537e05f 100644 --- a/src/traces/scatter/attributes.js +++ b/src/traces/scatter/attributes.js @@ -362,7 +362,9 @@ module.exports = { 'Determines whether or not markers and text nodes', 'are clipped about the subplot axes.', 'To show markers and text nodes above axis lines and tick labels,', - 'make sure to set `xaxis.layer` and `yaxis.layer` to *below traces*.' + 'make sure to set `xaxis.layer` and `yaxis.layer` to *below traces*.', + 'Defaults to *true*, except for bar traces with `textposition` set to *auto* or *outside*', + 'in which case the default is *false*.' ].join(' ') }, diff --git a/test/image/baselines/zz-pattern_bars-path.png b/test/image/baselines/zz-pattern_bars-path.png index cff51494b5b..a6405eab1fc 100644 Binary files a/test/image/baselines/zz-pattern_bars-path.png and b/test/image/baselines/zz-pattern_bars-path.png differ diff --git a/test/jasmine/tests/bar_test.js b/test/jasmine/tests/bar_test.js index 10e6413659b..cc11c9001d3 100644 --- a/test/jasmine/tests/bar_test.js +++ b/test/jasmine/tests/bar_test.js @@ -217,6 +217,65 @@ describe('Bar.supplyDefaults', function() { expect(traceOut.insidetextfont.size).toBe(20); }); + it('should set cliponaxis to false when text has value and textposition is outside', function() { + traceIn = { + y: [1, 2, 3], + text: ['A', 'B', 'C'], + textposition: 'outside' + }; + supplyDefaults(traceIn, traceOut, defaultColor, {}); + expect(traceOut.cliponaxis).toBe(false); + }); + + it('should set cliponaxis to false when text has value and textposition is auto', function() { + traceIn = { + y: [1, 2, 3], + text: ['A', 'B', 'C'], + textposition: 'auto' + }; + supplyDefaults(traceIn, traceOut, defaultColor, {}); + expect(traceOut.cliponaxis).toBe(false); + }); + + it('should set cliponaxis to false when text has value and textposition is unspecified', function() { + traceIn = { + y: [1, 2, 3], + text: ['A', 'B', 'C'], + }; + supplyDefaults(traceIn, traceOut, defaultColor, {}); + expect(traceOut.cliponaxis).toBe(false); + }); + + it('should set cliponaxis to default (true) when text is not provided', function() { + traceIn = { + y: [1, 2, 3], + textposition: 'outside' + }; + supplyDefaults(traceIn, traceOut, defaultColor, {}); + expect(traceOut.cliponaxis).toBe(true); + }); + + it('should set cliponaxis to default (true) when textposition is not outside', function() { + traceIn = { + y: [1, 2, 3], + text: ['A', 'B', 'C'], + textposition: 'inside' + }; + supplyDefaults(traceIn, traceOut, defaultColor, {}); + expect(traceOut.cliponaxis).toBe(true); + }); + + it('should respect explicit cliponaxis setting even with text and outside position', function() { + traceIn = { + y: [1, 2, 3], + text: ['A', 'B', 'C'], + textposition: 'outside', + cliponaxis: true + }; + supplyDefaults(traceIn, traceOut, defaultColor, {}); + expect(traceOut.cliponaxis).toBe(true); + }); + it('should inherit layout.calendar', function() { traceIn = { x: [1, 2, 3], diff --git a/test/plot-schema.json b/test/plot-schema.json index dbc320a4631..33d699f9615 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -58647,7 +58647,7 @@ "valType": "string" }, "cliponaxis": { - "description": "Determines whether or not markers and text nodes are clipped about the subplot axes. To show markers and text nodes above axis lines and tick labels, make sure to set `xaxis.layer` and `yaxis.layer` to *below traces*.", + "description": "Determines whether or not markers and text nodes are clipped about the subplot axes. To show markers and text nodes above axis lines and tick labels, make sure to set `xaxis.layer` and `yaxis.layer` to *below traces*. Defaults to *true*, except for bar traces with `textposition` set to *auto* or *outside* in which case the default is *false*.", "dflt": true, "editType": "plot", "valType": "boolean" @@ -74276,7 +74276,7 @@ "animatable": false, "attributes": { "cliponaxis": { - "description": "Determines whether or not markers and text nodes are clipped about the subplot axes. To show markers and text nodes above axis lines and tick labels, make sure to set `xaxis.layer` and `yaxis.layer` to *below traces*.", + "description": "Determines whether or not markers and text nodes are clipped about the subplot axes. To show markers and text nodes above axis lines and tick labels, make sure to set `xaxis.layer` and `yaxis.layer` to *below traces*. Defaults to *true*, except for bar traces with `textposition` set to *auto* or *outside* in which case the default is *false*.", "dflt": false, "editType": "plot", "valType": "boolean" @@ -78753,7 +78753,7 @@ "animatable": false, "attributes": { "cliponaxis": { - "description": "Determines whether or not markers and text nodes are clipped about the subplot axes. To show markers and text nodes above axis lines and tick labels, make sure to set `xaxis.layer` and `yaxis.layer` to *below traces*.", + "description": "Determines whether or not markers and text nodes are clipped about the subplot axes. To show markers and text nodes above axis lines and tick labels, make sure to set `xaxis.layer` and `yaxis.layer` to *below traces*. Defaults to *true*, except for bar traces with `textposition` set to *auto* or *outside* in which case the default is *false*.", "dflt": false, "editType": "plot", "valType": "boolean" @@ -81062,7 +81062,7 @@ "valType": "data_array" }, "cliponaxis": { - "description": "Determines whether or not markers and text nodes are clipped about the subplot axes. To show markers and text nodes above axis lines and tick labels, make sure to set `xaxis.layer` and `yaxis.layer` to *below traces*.", + "description": "Determines whether or not markers and text nodes are clipped about the subplot axes. To show markers and text nodes above axis lines and tick labels, make sure to set `xaxis.layer` and `yaxis.layer` to *below traces*. Defaults to *true*, except for bar traces with `textposition` set to *auto* or *outside* in which case the default is *false*.", "dflt": true, "editType": "plot", "valType": "boolean"