From 56c9ae74c29dd4bf0ded1ac6fdef6c76ec25c1d8 Mon Sep 17 00:00:00 2001 From: Vishwak Thatikonda Date: Tue, 11 Aug 2026 20:58:43 -0700 Subject: [PATCH] fix: truncate table header names with ellipsis instead of overlapping Header labels rendered in a grid cell without min-w-0 or whitespace-nowrap, so shrinking a column let the label's min-content width overflow the header cell and overlap the neighboring column. The text-ellipsis class was also gated on a per-column overflow option that Data Explorer never sets, and without nowrap it had no effect anyway. Header labels now always truncate with an ellipsis, and string headers carry a title attribute so hovering reveals the full name. Fixes #2083 --- .../components/Tabular/TabularHeader.test.tsx | 49 +++++++++++++++++++ .../src/components/Tabular/TabularHeader.tsx | 8 ++- 2 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 packages/graph-explorer/src/components/Tabular/TabularHeader.test.tsx diff --git a/packages/graph-explorer/src/components/Tabular/TabularHeader.test.tsx b/packages/graph-explorer/src/components/Tabular/TabularHeader.test.tsx new file mode 100644 index 000000000..b9462ea36 --- /dev/null +++ b/packages/graph-explorer/src/components/Tabular/TabularHeader.test.tsx @@ -0,0 +1,49 @@ +// @vitest-environment happy-dom +import { render, screen } from "@testing-library/react"; +import { describe, expect, it } from "vitest"; + +import type { ColumnDefinition } from "./useTabular"; + +import Tabular from "./Tabular"; + +type Row = { veryLongAttributeName: string; short: string }; + +const data: Row[] = [{ veryLongAttributeName: "value", short: "v" }]; + +function renderTable(columns: ColumnDefinition[]) { + render(); +} + +describe("TabularHeader", () => { + it("truncates the header label and reveals the full name on hover", () => { + renderTable([ + { + id: "veryLongAttributeName", + label: "A Very Long Attribute Name That Overflows", + accessor: "veryLongAttributeName", + }, + ]); + + const label = screen.getByTitle( + "A Very Long Attribute Name That Overflows", + ); + expect(label).toHaveTextContent( + "A Very Long Attribute Name That Overflows", + ); + expect(label.className).toContain("truncate"); + }); + + it("omits the title when the header is not a plain string", () => { + renderTable([ + { + id: "short", + label: "Short", + headerComponent: () => Custom Header, + accessor: "short", + }, + ]); + + expect(screen.getByText("Custom Header")).toBeInTheDocument(); + expect(screen.queryByTitle("Short")).toBeNull(); + }); +}); diff --git a/packages/graph-explorer/src/components/Tabular/TabularHeader.tsx b/packages/graph-explorer/src/components/Tabular/TabularHeader.tsx index 3a17d8a15..b26ca192e 100644 --- a/packages/graph-explorer/src/components/Tabular/TabularHeader.tsx +++ b/packages/graph-explorer/src/components/Tabular/TabularHeader.tsx @@ -41,9 +41,13 @@ const TabularHeader = ({ )} >
{column.render("Header")}