From 9f5e15e560e4204bf206205fe7baaf37a79cf54f Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 7 Sep 2026 22:38:10 +0000 Subject: [PATCH] fix(kanban): keep the swimlane column-header row out of the flex shrink pool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With swimlanes on, the board's column titles stayed in the DOM at height 0 and painted nothing (objectui#7303). The header row is a flex item of the swimlane region, and `overflow-x-auto` makes it a scroll container — which zeroes a flex item's automatic minimum size, so it may legally shrink to 0. The lanes below stay `overflow: visible`, so their automatic minimum size clamps them at content height and they refuse to shrink; once the lanes overflowed the bounded board, the entire deficit landed on the one shrinkable item. `shrink-0` takes the row out of that pool. Measured in Chromium 1194 at 1600x1000 on the component's own rendered markup: header row 0 -> 24, header cell 0 -> 24, and `elementFromPoint` at a title's centre returning the lane-collapse button before and the title itself after. The pin asserts the style contract that decides the height, not the row's existence — the row was present and correctly placed on the broken build — and carries a rendered lane, a rendered card and the flat board's own headings as controls. happy-dom performs no layout, so a height assertion there could not fail; the docstring says so and records the out-of-band measurement instead. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S --- .../7303-kanban-swimlane-column-header-row.md | 32 +++ packages/plugin-kanban/src/KanbanImpl.tsx | 30 ++- .../swimlaneColumnHeaderRow-7303.test.tsx | 252 ++++++++++++++++++ 3 files changed, 312 insertions(+), 2 deletions(-) create mode 100644 .changeset/7303-kanban-swimlane-column-header-row.md create mode 100644 packages/plugin-kanban/src/__tests__/swimlaneColumnHeaderRow-7303.test.tsx diff --git a/.changeset/7303-kanban-swimlane-column-header-row.md b/.changeset/7303-kanban-swimlane-column-header-row.md new file mode 100644 index 0000000000..ead1cb2215 --- /dev/null +++ b/.changeset/7303-kanban-swimlane-column-header-row.md @@ -0,0 +1,32 @@ +--- +'@object-ui/plugin-kanban': patch +--- + +Keep the kanban column-header row visible when swimlanes are on (objectui#7303). + +Turning swimlanes on for a board — `grouping.fields[0].field`, which is the only +authorable route, since `KanbanConfigSchema` is strict and rejects +`kanban.swimlaneField` — removed the status column titles from the screen. They +stayed in the DOM, at the right coordinates, painting nothing, so the board read +as an unordered card wall: the lane told you the caliber of the work and nothing +told you its state. + +The cause is a flexbox rule rather than a paint bug. The header row is a flex +item of the swimlane region (a `flex-col` inside a height-bounded board), and its +`overflow-x-auto` makes it a scroll container — which zeroes a flex item's +automatic minimum size, so it may legally be shrunk to height 0. The lanes below +keep `overflow: visible`, so their own automatic minimum size clamps them at +content height and they refuse to shrink; the moment the lanes overflowed the +board, the entire deficit landed on the one shrinkable item. The row now carries +`shrink-0`, which takes it out of that pool. + +Note the trigger, because it decides who saw this: the collapse needed the lanes +to OVERFLOW the board's bounded height. A board short enough to fit rendered its +titles normally, which is why this presented in the field as "sometimes the +column labels are missing" rather than as a flat breakage of swimlanes. + +Measured in Chromium 1194 at 1600×1000 on the component's own rendered markup: +header row height 0 → 24, header cell 0 → 24, and `elementFromPoint` at a title's +own centre returning the lane-collapse button before the fix and the title itself +after it. Nothing else about the layout moves — the row keeps its `pl-36 sm:pl-44` +alignment with the lane content rows, and the non-swimlane board is untouched. diff --git a/packages/plugin-kanban/src/KanbanImpl.tsx b/packages/plugin-kanban/src/KanbanImpl.tsx index 77333ccd63..a834767db1 100644 --- a/packages/plugin-kanban/src/KanbanImpl.tsx +++ b/packages/plugin-kanban/src/KanbanImpl.tsx @@ -655,8 +655,34 @@ function KanbanBoardInner({ columns, onCardMove, onCardClick, className, dnd, qu {swimlanes ? ( /* Swimlane (2D) layout */
- {/* Column headers */} -
+ {/* Column headers. + This is a SECOND header implementation, parallel to the per-column + `

` that `KanbanColumnView` + renders. The two cannot be folded into one: this layout has no + column components at all — every lane paints its own row of plain + column cells — so the titles have to be drawn once, above every + lane, instead of once per column. + + `shrink-0` is load-bearing, not cosmetic (objectui#7303). This row + is a flex ITEM of the swimlane region, which is a `flex-col` inside + a height-bounded board (`h-full`). `overflow-x-auto` makes the row + a scroll container, and a flex item's automatic minimum size + (`min-height: auto`) applies only while its overflow is `visible` + — so as a scroll container this row may legally be shrunk to + height 0. The lanes below stay `overflow: visible`, so their own + automatic minimum size clamps them at content height and they + refuse to shrink: the moment the lanes overflow the board, the + ENTIRE deficit lands on this one shrinkable item. The titles then + stay in the DOM, at the right coordinates, painting nothing. + Measured in Chromium 1194 at 1600x1000 before the fix: row height + 0, cell height 0, title span height 16, and `elementFromPoint` at + a title's own centre returning the lane-collapse `