From 960fa750b0be361fdade958d1c7521431323d1a1 Mon Sep 17 00:00:00 2001 From: colivi Date: Sat, 31 Oct 2026 19:12:48 +0100 Subject: [PATCH] fix(piechart): hide slice labels that do not fit Inner labels overlap when a slice is too small to hold the text. Skip slices under 5% and drop a label that still collides with another. Signed-off-by: colivi --- piechart/src/PieChartBase.test.tsx | 20 +++++++++++++++++++- piechart/src/PieChartBase.tsx | 3 +++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/piechart/src/PieChartBase.test.tsx b/piechart/src/PieChartBase.test.tsx index bc670bee4..7be840137 100644 --- a/piechart/src/PieChartBase.test.tsx +++ b/piechart/src/PieChartBase.test.tsx @@ -16,7 +16,7 @@ import type * as Components from '@perses-dev/components'; import { render } from '@testing-library/react'; import type { PieChartData } from './PieChartBase'; -import { PieChartBase } from './PieChartBase'; +import { MIN_SHOW_LABEL_ANGLE, PieChartBase } from './PieChartBase'; const { eChartSpy } = vi.hoisted(() => ({ eChartSpy: vi.fn() })); @@ -38,7 +38,9 @@ interface EChartProps { emphasis: { scaleSize: number; }; + labelLayout: { hideOverlap: boolean }; left: number; + minShowLabelAngle: number; radius: string | [string, string]; right: number; top: number; @@ -91,4 +93,20 @@ describe('PieChartBase', () => { const props = eChartSpy.mock.lastCall?.[0] as EChartProps; expect(props.option.series[0]?.radius).toEqual(DONUT_RADIUS); }); + + it('omits labels that cannot fit in a slice', () => { + render( + + + , + ); + + const props = eChartSpy.mock.lastCall?.[0] as EChartProps; + expect(props.option.series[0]).toEqual( + expect.objectContaining({ + minShowLabelAngle: MIN_SHOW_LABEL_ANGLE, + labelLayout: { hideOverlap: true }, + }), + ); + }); }); diff --git a/piechart/src/PieChartBase.tsx b/piechart/src/PieChartBase.tsx index 21a4821c8..0337be830 100644 --- a/piechart/src/PieChartBase.tsx +++ b/piechart/src/PieChartBase.tsx @@ -40,6 +40,7 @@ const CONTAINER_SX = { overflow: 'auto' }; const EMPHASIS_SHADOW_BLUR = 10; const EMPHASIS_SCALE_SIZE = 5; const PIE_INSET = EMPHASIS_SHADOW_BLUR + EMPHASIS_SCALE_SIZE; +export const MIN_SHOW_LABEL_ANGLE = 360 * 0.05; export interface PieChartData { id?: string; name: string; @@ -99,6 +100,8 @@ export function PieChartBase(props: PieChartBaseProps): ReactElement { right: PIE_INSET, top: PIE_INSET, bottom: PIE_INSET, + minShowLabelAngle: MIN_SHOW_LABEL_ANGLE, + labelLayout: { hideOverlap: true }, label: { show: Boolean(showLabels), position: 'inner',