This is an automated email from the ASF dual-hosted git repository. rusackas pushed a commit to branch feat/bignumber-alignment-control in repository https://gitbox.apache.org/repos/asf/superset.git
commit d9b2d8dc0c0be065fc19dbdae0dbbed8ccbf2009 Author: Evan Rusackas <[email protected]> AuthorDate: Tue Sep 22 18:59:23 2026 -0700 feat(bignumber): add an alignment control for Big Number charts Superset 5 centered the Big Number value and subheader; the Emotion CSS-in-JS migration hardcoded align-items: flex-start on the shared BigNumberViz component, and there's been no way back since (#37674). Adds a header_alignment control (Left/Center/Right, default Left to match current behavior) to both BigNumberTotal and BigNumberWithTrendline, threaded through transformProps into BigNumberVizProps. BigNumberViz applies it as align-items on the outer container and text-container, and text-align on each text line (metric name, kicker, header, subheader, subtitle), so multi-line wrapped text aligns internally too. Scoped to alignment only: doesn't touch axis/grid config, context menu wiring, conditional formatting, or aggregation logic. Co-Authored-By: Evan Rusackas <[email protected]> Co-Authored-By: Claude Sonnet 5 <[email protected]> --- .../BigNumber/BigNumberTotal/controlPanel.test.ts | 10 ++++ .../src/BigNumber/BigNumberTotal/controlPanel.ts | 2 + .../BigNumberTotal/transformProps.test.ts | 2 + .../src/BigNumber/BigNumberTotal/transformProps.ts | 2 + .../src/BigNumber/BigNumberViz.test.tsx | 67 ++++++++++++++++++++++ .../src/BigNumber/BigNumberViz.tsx | 21 ++++++- .../BigNumberWithTrendline/controlPanel.tsx | 2 + .../BigNumberWithTrendline/transformProps.test.ts | 2 + .../BigNumberWithTrendline/transformProps.ts | 2 + .../src/BigNumber/sharedControls.ts | 19 ++++++ .../plugin-chart-echarts/src/BigNumber/types.ts | 4 ++ 11 files changed, 130 insertions(+), 3 deletions(-) diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/controlPanel.test.ts b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/controlPanel.test.ts index 7d8e74156d4..a71d3520a48 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/controlPanel.test.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/controlPanel.test.ts @@ -72,6 +72,16 @@ describe('BigNumber Total Control Panel Config', () => { row.some((control: any) => control.name === 'conditional_formatting'), ); expect(conditionalFormattingRow).toBeTruthy(); + + // Check header_alignment control exists in one of the rows + const headerAlignmentRow = thirdSection.find(row => + row.some((control: any) => control.name === 'header_alignment'), + ); + expect(headerAlignmentRow).toBeTruthy(); + expect(headerAlignmentRow![0]).toMatchObject({ + name: 'header_alignment', + config: expect.objectContaining({ default: 'left' }), + }); }); test('should have y_axis_format override with correct label', () => { diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/controlPanel.ts b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/controlPanel.ts index d926f06de01..906b01e91c9 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/controlPanel.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/controlPanel.ts @@ -32,6 +32,7 @@ import { subtitleControl, showMetricNameControl, metricNameFontSizeWithVisibility, + headerAlignmentControl, } from '../sharedControls'; export default { @@ -124,6 +125,7 @@ export default { }, }, ], + [headerAlignmentControl], ], }, ], diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/transformProps.test.ts b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/transformProps.test.ts index 00522b9d0a8..54f5898c949 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/transformProps.test.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/transformProps.test.ts @@ -54,6 +54,7 @@ describe('BigNumberTotal transformProps', () => { yAxisFormat: 'SMART_NUMBER', conditionalFormatting: [{ color: 'red', op: '>', value: 0 }], currencyFormat: { symbol: '$', symbolPosition: 'prefix' }, + headerAlignment: 'center', }; const baseDatasource = { @@ -86,6 +87,7 @@ describe('BigNumberTotal transformProps', () => { expect(result.subtitle).toBe(baseFormData.subheader); expect(result.onContextMenu).toBe(onContextMenu); expect(result.refs).toEqual({}); + expect(result.headerAlignment).toBe('center'); // headerFormatter should be set even if there's no data expect(typeof result.headerFormatter).toBe('function'); // colorThresholdFormatters fallback to empty array when getColorFormatters returns falsy diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/transformProps.ts index 3c7c78ecc70..2d7df441c31 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/transformProps.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/transformProps.ts @@ -63,6 +63,7 @@ export default function transformProps( currencyFormat, subheader, subheaderFontSize, + headerAlignment, } = formData; const refs: Refs = {}; const { @@ -143,5 +144,6 @@ export default function transformProps( metricName: originalLabel, showMetricName, metricNameFontSize, + headerAlignment, }; } diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.test.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.test.tsx index dd7a495ee89..5279056a7f5 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.test.tsx +++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.test.tsx @@ -117,3 +117,70 @@ describe('BigNumberViz context menu', () => { expect(ancestorHandler).not.toHaveBeenCalled(); }); }); + +describe('BigNumberViz alignment', () => { + test('defaults to left alignment', () => { + const { container } = render( + <BigNumberVis + width={200} + height={100} + bigNumber={42} + headerFormatter={getNumberFormatter()} + headerFontSize={0.3} + subheaderFontSize={0.125} + subtitleFontSize={0.125} + subtitle="" + refs={{}} + />, + ); + + const textContainer = container.querySelector('.text-container'); + expect(textContainer).toHaveStyle({ alignItems: 'flex-start' }); + const headerLine = container.querySelector('.header-line'); + expect(headerLine).toHaveStyle({ textAlign: 'left' }); + }); + + test('centers content when headerAlignment is "center"', () => { + const { container } = render( + <BigNumberVis + width={200} + height={100} + bigNumber={42} + headerFormatter={getNumberFormatter()} + headerFontSize={0.3} + subheaderFontSize={0.125} + subtitleFontSize={0.125} + subtitle="" + refs={{}} + headerAlignment="center" + />, + ); + + const textContainer = container.querySelector('.text-container'); + expect(textContainer).toHaveStyle({ alignItems: 'center' }); + const headerLine = container.querySelector('.header-line'); + expect(headerLine).toHaveStyle({ textAlign: 'center' }); + }); + + test('right-aligns content when headerAlignment is "right"', () => { + const { container } = render( + <BigNumberVis + width={200} + height={100} + bigNumber={42} + headerFormatter={getNumberFormatter()} + headerFontSize={0.3} + subheaderFontSize={0.125} + subtitleFontSize={0.125} + subtitle="" + refs={{}} + headerAlignment="right" + />, + ); + + const textContainer = container.querySelector('.text-container'); + expect(textContainer).toHaveStyle({ alignItems: 'flex-end' }); + const headerLine = container.querySelector('.header-line'); + expect(headerLine).toHaveStyle({ textAlign: 'right' }); + }); +}); diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.tsx index ea4e89cd0ee..e16e7efc149 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.tsx +++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.tsx @@ -28,12 +28,18 @@ import { } from '@superset-ui/core'; import { styled, useTheme } from '@apache-superset/core/theme'; import Echart from '../components/Echart'; -import { BigNumberVizProps } from './types'; +import { BigNumberVizProps, HeaderAlignment } from './types'; import { PROPORTION } from './constants'; import { EventHandlers } from '../types'; const defaultNumberFormatter = getNumberFormatter(); +const ALIGN_ITEMS: Record<HeaderAlignment, string> = { + left: 'flex-start', + center: 'center', + right: 'flex-end', +}; + function BigNumberVis({ className = '', headerFormatter = defaultNumberFormatter, @@ -47,9 +53,11 @@ function BigNumberVis({ subheader = '', subheaderFontSize = PROPORTION.SUBHEADER, subtitleFontSize = PROPORTION.SUBHEADER, + headerAlignment = 'left', ...props }: BigNumberVizProps) { const theme = useTheme(); + const alignItems = ALIGN_ITEMS[headerAlignment]; // Convert state to hooks const [elementsRendered, setElementsRendered] = useState(false); @@ -132,6 +140,7 @@ function BigNumberVis({ style={{ fontSize, height: 'auto', + textAlign: headerAlignment, }} > {text} @@ -170,6 +179,7 @@ function BigNumberVis({ style={{ fontSize, height: 'auto', + textAlign: headerAlignment, }} > {text} @@ -239,6 +249,7 @@ function BigNumberVis({ fontSize, height: 'auto', color: numberColor, + textAlign: headerAlignment, }} onContextMenu={handleContextMenu} > @@ -275,6 +286,7 @@ function BigNumberVis({ style={{ fontSize, height: maxHeight, + textAlign: headerAlignment, }} > {text} @@ -321,6 +333,7 @@ function BigNumberVis({ style={{ fontSize: `${fontSize}px`, height: maxHeight, + textAlign: headerAlignment, }} > {text} @@ -425,11 +438,12 @@ function BigNumberVis({ const overflow = shouldApplyOverflow(allTextHeight); return ( - <div className={componentClassName}> + <div className={componentClassName} style={{ alignItems }}> <div className="text-container" style={{ height: allTextHeight, + alignItems, ...(overflow ? { display: 'block', @@ -472,6 +486,7 @@ function BigNumberVis({ className={componentClassName} style={{ height, + alignItems, ...(overflow ? { display: 'block', @@ -483,7 +498,7 @@ function BigNumberVis({ : {}), }} > - <div className="text-container"> + <div className="text-container" style={{ alignItems }}> {renderFallbackWarning()} {renderMetricName((metricNameFontSize || 0) * height)} {renderKicker((kickerFontSize || 0) * height)} diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/controlPanel.tsx index d9d5b85a1cc..762fe6ad94c 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/controlPanel.tsx +++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/controlPanel.tsx @@ -35,6 +35,7 @@ import { subtitleControl, showMetricNameControl, metricNameFontSizeWithVisibility, + headerAlignmentControl, } from '../sharedControls'; const config: ControlPanelConfig = { @@ -235,6 +236,7 @@ const config: ControlPanelConfig = { }, }, ], + [headerAlignmentControl], ], }, { diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.test.ts b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.test.ts index 6a9752d57b9..8e7816994a9 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.test.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.test.ts @@ -113,6 +113,7 @@ describe('BigNumberWithTrendline transformProps', () => { compareSuffix: 'WoW', colorPicker: { r: 0, g: 0, b: 0 }, currencyFormat: { symbol: '$', symbolPosition: 'prefix' }, + headerAlignment: 'right', }; const baseDatasource = { @@ -141,6 +142,7 @@ describe('BigNumberWithTrendline transformProps', () => { ); expect(result.bigNumber).toBeNull(); expect(result.subtitle).toBe('subtitle message'); + expect(result.headerAlignment).toBe('right'); }); test('should calculate subheader as percent change with suffix', () => { diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.ts index fa57d2a8b71..9b4a4640e74 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.ts @@ -114,6 +114,7 @@ export default function transformProps( showXAxisMinMaxLabels = false, showYAxis = false, showYAxisMinMaxLabels = false, + headerAlignment, } = formData; const granularity = extractTimegrain(rawFormData); const { @@ -416,5 +417,6 @@ export default function transformProps( onContextMenu, xValueFormatter: formatTime, refs, + headerAlignment, }; } diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/sharedControls.ts b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/sharedControls.ts index 5c7647fa576..44c2f1d7267 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/sharedControls.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/sharedControls.ts @@ -113,3 +113,22 @@ export const metricNameFontSizeWithVisibility: CustomControlItem = { resetOnHide: false, }, }; + +export const headerAlignmentControl: CustomControlItem = { + name: 'header_alignment', + config: { + type: 'SelectControl', + label: t('Alignment'), + renderTrigger: true, + clearable: false, + default: 'left', + options: [ + { label: t('Left'), value: 'left' }, + { label: t('Center'), value: 'center' }, + { label: t('Right'), value: 'right' }, + ], + description: t( + 'Horizontal alignment of the metric value and supporting text', + ), + }, +}; diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/types.ts b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/types.ts index d466a1781c8..d069b79219e 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/types.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/types.ts @@ -34,10 +34,13 @@ export interface BigNumberDatum { [key: string]: number | string | null; } +export type HeaderAlignment = 'left' | 'center' | 'right'; + export type BigNumberTotalFormData = QueryFormData & { metric?: QueryFormMetric; yAxisFormat?: string; forceTimestampFormatting?: boolean; + headerAlignment?: HeaderAlignment; }; export type BigNumberWithTrendlineFormData = BigNumberTotalFormData & { @@ -107,4 +110,5 @@ export type BigNumberVizProps = { formData?: BigNumberWithTrendlineFormData; refs: Refs; colorThresholdFormatters?: ColorFormatters; + headerAlignment?: HeaderAlignment; };
