From f66356c8bbeec0260cd56258a27ed08387f42610 Mon Sep 17 00:00:00 2001 From: Krishn <1khandelwalnhk@gmail.com> Date: Thu, 6 Aug 2026 12:18:11 +0530 Subject: [PATCH] fix(plugin-chart-echarts): hide value labels on zero-height stacked segments thresholdValues[dataIndex] is 0 when percentage_threshold is 0, which is falsy, so the guard fell back to Number.MIN_SAFE_INTEGER and every value passed. A zero-value series occupies no space in a stacked chart, so its label rendered on top of the adjacent segment's label. Skips the label when the value is exactly 0 while leaving negative values and non-zero thresholds untouched. Fixes #42702 Co-Authored-By: Claude Opus 5 --- .../src/Timeseries/transformers.ts | 6 +- .../test/Timeseries/transformers.test.ts | 69 ++++++++++++++++++- 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformers.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformers.ts index 6d167787d3da..29f135f3de56 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformers.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformers.ts @@ -467,9 +467,13 @@ export function transformSeries( return formatter(numericValue); } if (!onlyTotal) { + // A zero value occupies no space in a stacked series, so its label + // would render on top of the adjacent segment's label. Skip it + // regardless of the threshold. if ( + numericValue !== 0 && numericValue >= - (thresholdValues[dataIndex] || Number.MIN_SAFE_INTEGER) + (thresholdValues[dataIndex] || Number.MIN_SAFE_INTEGER) ) { return formatter(numericValue); } diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformers.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformers.test.ts index 84022759a503..6e043faa2bc4 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformers.test.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformers.test.ts @@ -26,7 +26,10 @@ import { supersetTheme } from '@apache-superset/core/theme'; import type { SeriesOption } from 'echarts'; import type { ScatterSeriesOption } from 'echarts/charts'; import { EchartsTimeseriesSeriesType } from '../../src'; -import { TIMESERIES_CONSTANTS } from '../../src/constants'; +import { + TIMESERIES_CONSTANTS, + StackControlsValue, +} from '../../src/constants'; import { LegendOrientation, EchartsTimeseriesChartProps, @@ -87,6 +90,70 @@ describe('transformSeries', () => { ); }); + describe('stacked value labels', () => { + // Two series stacked on one category: A is 32, B is 0. The zero-height + // B segment must not render a label over A's label. + const buildFormatter = (thresholdValues: number[]) => { + const result = transformSeries(series, mockColorScale, 'test-key', { + showValue: true, + stack: StackControlsValue.Stack, + onlyTotal: false, + formatter: (v: any) => String(v), + totalStackedValues: [32], + thresholdValues, + }); + return (result as any).label.formatter; + }; + + test('hides the label for a zero value when the threshold is 0', () => { + const formatter = buildFormatter([0]); + expect( + formatter({ + value: [0, 0], + dataIndex: 0, + seriesIndex: 1, + seriesName: 'B', + }), + ).toBe(''); + }); + + test('still shows the label for a non-zero value when the threshold is 0', () => { + const formatter = buildFormatter([0]); + expect( + formatter({ + value: [0, 32], + dataIndex: 0, + seriesIndex: 0, + seriesName: 'A', + }), + ).toBe('32'); + }); + + test('still shows the label for a negative value when the threshold is 0', () => { + const formatter = buildFormatter([0]); + expect( + formatter({ + value: [0, -5], + dataIndex: 0, + seriesIndex: 0, + seriesName: 'A', + }), + ).toBe('-5'); + }); + + test('keeps hiding values below a non-zero threshold', () => { + const formatter = buildFormatter([16]); + expect( + formatter({ + value: [0, 4], + dataIndex: 0, + seriesIndex: 0, + seriesName: 'A', + }), + ).toBe(''); + }); + }); + test('should not apply border styles for non-bar series', () => { const opts = { seriesType: EchartsTimeseriesSeriesType.Line,