From 3c37046cf84500979d17e1ba3d34bc75be17e389 Mon Sep 17 00:00:00 2001 From: maxkoretskyi Date: Sat, 7 Feb 2026 13:17:18 +0100 Subject: [PATCH] fix: align table column headers with text_justify_columns setting (#7967) --- .../data-table/__tests__/columns.test.tsx | 47 +++++++++++++++++++ .../components/data-table/column-header.tsx | 25 +++++++++- .../src/components/data-table/columns.tsx | 1 + 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/data-table/__tests__/columns.test.tsx b/frontend/src/components/data-table/__tests__/columns.test.tsx index 7599840706a..96e01cb1f32 100644 --- a/frontend/src/components/data-table/__tests__/columns.test.tsx +++ b/frontend/src/components/data-table/__tests__/columns.test.tsx @@ -243,6 +243,53 @@ describe("generateColumns", () => { expect(cell?.props.className).toContain("center"); }); + it("should apply text justification to column headers", () => { + const columns = generateColumns({ + rowHeaders: [], + selection: null, + fieldTypes, + textJustifyColumns: { name: "right", age: "center" }, + }); + + const mockColumn = (col: (typeof columns)[number]) => ({ + id: col.id, + getCanSort: () => true, + getCanFilter: () => false, + getIsSorted: () => false, + getSortIndex: () => -1, + getFilterValue: () => undefined, + columnDef: { meta: col.meta }, + }); + + // Right-justified header should have flex-row-reverse and text-right + const { container: rightContainer } = render( + + {/* eslint-disable-next-line @typescript-eslint/no-explicit-any */} + {(columns[0].header as any)({ column: mockColumn(columns[0]) })} + , + ); + const rightHeader = rightContainer.querySelector( + "[data-testid='data-table-sort-button']", + ); + expect(rightHeader?.className).toContain("flex-row-reverse"); + const rightSpan = rightHeader?.querySelector("span"); + expect(rightSpan?.className).toContain("text-right"); + + // Center-justified header should have text-center but not flex-row-reverse + const { container: centerContainer } = render( + + {/* eslint-disable-next-line @typescript-eslint/no-explicit-any */} + {(columns[1].header as any)({ column: mockColumn(columns[1]) })} + , + ); + const centerHeader = centerContainer.querySelector( + "[data-testid='data-table-sort-button']", + ); + expect(centerHeader?.className).not.toContain("flex-row-reverse"); + const centerSpan = centerHeader?.querySelector("span"); + expect(centerSpan?.className).toContain("text-center"); + }); + it("should not include index column if it exists", () => { const columns = generateColumns({ rowHeaders: [], diff --git a/frontend/src/components/data-table/column-header.tsx b/frontend/src/components/data-table/column-header.tsx index 315bc4860d0..6b82911276e 100644 --- a/frontend/src/components/data-table/column-header.tsx +++ b/frontend/src/components/data-table/column-header.tsx @@ -67,6 +67,7 @@ interface DataTableColumnHeaderProps extends React.HTMLAttributes { column: Column; header: React.ReactNode; + justify?: "left" | "center" | "right"; calculateTopKRows?: CalculateTopKRows; table?: Table; } @@ -74,6 +75,7 @@ interface DataTableColumnHeaderProps export const DataTableColumnHeader = ({ column, header, + justify, className, calculateTopKRows, table, @@ -88,7 +90,17 @@ export const DataTableColumnHeader = ({ // No sorting or filtering if (!column.getCanSort() && !column.getCanFilter()) { - return
{header}
; + return ( +
+ {header} +
+ ); } const hasFilter = column.getFilterValue() !== undefined; @@ -101,11 +113,20 @@ export const DataTableColumnHeader = ({
- {header} + + {header} + ({