This is an automated email from the ASF dual-hosted git repository.
rusackas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new 4ae8fe71225 fix: size 'Drill to detail' table header correctly (#44807)
4ae8fe71225 is described below
commit 4ae8fe712250851cf285cdecafee336470179766
Author: mattmc3 <[email protected]>
AuthorDate: Thu Oct 1 19:50:28 2026 -0400
fix: size 'Drill to detail' table header correctly (#44807)
---
.../src/components/Table/VirtualTable.test.tsx | 83 ++++++++++++++++++++++
.../src/components/Table/VirtualTable.tsx | 20 +++---
2 files changed, 95 insertions(+), 8 deletions(-)
diff --git
a/superset-frontend/packages/superset-ui-core/src/components/Table/VirtualTable.test.tsx
b/superset-frontend/packages/superset-ui-core/src/components/Table/VirtualTable.test.tsx
index f78c55a9381..1a984afd54f 100644
---
a/superset-frontend/packages/superset-ui-core/src/components/Table/VirtualTable.test.tsx
+++
b/superset-frontend/packages/superset-ui-core/src/components/Table/VirtualTable.test.tsx
@@ -20,6 +20,28 @@ import { render, screen, waitFor } from
'@superset-ui/core/spec';
import type { ColumnsType } from 'antd/es/table';
import { Table } from './index';
+// jsdom never measures the container, so tests that need a width set this one.
+let mockTableWidth: number | undefined;
+jest.mock('react-resize-detector', () => {
+ const { useEffect } = jest.requireActual('react');
+ return {
+ useResizeDetector: ({
+ onResize,
+ }: {
+ onResize?: (width?: number) => void;
+ }) => {
+ useEffect(() => {
+ if (mockTableWidth !== undefined) onResize?.(mockTableWidth);
+ }, [onResize]);
+ return { ref: () => undefined };
+ },
+ };
+});
+
+afterEach(() => {
+ mockTableWidth = undefined;
+});
+
// These tests exercise VirtualTable's react-window v2 `Grid` wiring
// (`cellComponent`/`cellProps`/`gridRef`), which previously had no direct
// coverage - `Table.test.tsx` only exercises the non-virtualized code path.
@@ -120,3 +142,64 @@ test('cell render functions receive their row data via
cellProps rather than a s
expect(screen.getByText('rendered:Number')).toBeInTheDocument();
});
});
+
+// The header is antd's own <table>; the body Grid is sized to the columns.
+const virtualHeaderWidth = (columns: ColumnsType<BasicData>) => {
+ const { container } = render(
+ <Table
+ columns={columns}
+ data={testData}
+ virtualize
+ height={200}
+ usePagination={false}
+ />,
+ );
+ return () =>
+ container
+ .querySelector<HTMLTableElement>('.virtual-table thead')
+ ?.closest('table')?.style.width;
+};
+
+test('virtualized table header is as wide as its columns, not the viewport',
async () => {
+ const width = virtualHeaderWidth(testColumns);
+ await waitFor(() => expect(width()).toBe('300px'));
+});
+
+test('virtualized table header width ignores non-numeric column widths', async
() => {
+ const width = virtualHeaderWidth([
+ testColumns[0],
+ { ...testColumns[1], width: '20%' },
+ ]);
+ await waitFor(() => expect(width()).toBe('150px'));
+});
+
+test('virtualized table header width survives a non-numeric width beside an
unsized column', async () => {
+ const width = virtualHeaderWidth([
+ { ...testColumns[0], width: '20%' },
+ { title: 'Column Type', dataIndex: 'columnType', key: 'columnType' },
+ ]);
+ // The unsized column gets the 50px minimum; the '20%' one adds nothing.
+ await waitFor(() => expect(width()).toBe('50px'));
+});
+
+test('virtualized table header includes the stretched last column', async ()
=> {
+ mockTableWidth = 400;
+ const width = virtualHeaderWidth(testColumns);
+ await waitFor(() => expect(width()).toBe('400px'));
+});
+
+test('virtualized table does not stretch a non-numeric last column', async ()
=> {
+ mockTableWidth = 400;
+ const width = virtualHeaderWidth([
+ testColumns[0],
+ { ...testColumns[1], width: '20%' },
+ ]);
+ await waitFor(() => expect(width()).toBe('150px'));
+});
+
+test('virtualized table header falls back to the given scroll.x when no width
is numeric', async () => {
+ const width = virtualHeaderWidth(
+ testColumns.map(column => ({ ...column, width: '50%' })),
+ );
+ await waitFor(() => expect(width()).toBe('100vw'));
+});
diff --git
a/superset-frontend/packages/superset-ui-core/src/components/Table/VirtualTable.tsx
b/superset-frontend/packages/superset-ui-core/src/components/Table/VirtualTable.tsx
index 53ef9f30e0a..585eda982a2 100644
---
a/superset-frontend/packages/superset-ui-core/src/components/Table/VirtualTable.tsx
+++
b/superset-frontend/packages/superset-ui-core/src/components/Table/VirtualTable.tsx
@@ -152,11 +152,12 @@ const VirtualTable = <RecordType extends object>(
const widthColumnCount = columns!.filter(({ width }) => !width).length;
let staticColWidthTotal = 0;
columns?.forEach(column => {
- if (column.width) {
- staticColWidthTotal += column.width as number;
+ if (typeof column.width === 'number') {
+ staticColWidthTotal += column.width;
}
});
+ // Sum of numeric widths; also sizes the antd header (scroll.x) to match the
Grid.
let totalWidth = 0;
const defaultWidth = Math.max(
Math.floor((tableWidth - staticColWidthTotal) / widthColumnCount),
@@ -169,7 +170,9 @@ const VirtualTable = <RecordType extends object>(
if (!column.width) {
modifiedColumn.width = defaultWidth;
}
- totalWidth += modifiedColumn.width as number;
+ if (typeof modifiedColumn.width === 'number') {
+ totalWidth += modifiedColumn.width;
+ }
return modifiedColumn;
}) ?? [];
@@ -177,10 +180,11 @@ const VirtualTable = <RecordType extends object>(
* There are cases where a user could set the width of each column and the
total width is less than width of
* the table. In this case we will stretch the last column to use the extra
space
*/
- if (totalWidth < tableWidth) {
- const lastColumn = mergedColumns[mergedColumns.length - 1];
- lastColumn.width =
- (lastColumn.width as number) + Math.floor(tableWidth - totalWidth);
+ const lastColumn = mergedColumns[mergedColumns.length - 1];
+ if (totalWidth < tableWidth && typeof lastColumn?.width === 'number') {
+ const extra = Math.floor(tableWidth - totalWidth);
+ lastColumn.width += extra;
+ totalWidth += extra;
}
const gridRef = useRef<GridImperativeAPI>(null);
@@ -288,7 +292,7 @@ const VirtualTable = <RecordType extends object>(
body: renderVirtualList,
}}
pagination={pagination ? modifiedPagination : false}
- scroll={scroll}
+ scroll={{ ...scroll, x: totalWidth || scroll?.x }}
columns={mergedColumns}
/>
</div>