From 1332f5626b9dbb69477959b76c4c2da09761e7d2 Mon Sep 17 00:00:00 2001 From: Thomas Camlong Date: Sun, 9 Aug 2026 09:41:08 +0200 Subject: [PATCH] fix: stabilize board rails --- .../boards/(content)/_client.module.css | 40 +++++++++++++++++-- e2e/board-grid.spec.ts | 8 ++++ 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/apps/nextjs/src/app/[locale]/boards/(content)/_client.module.css b/apps/nextjs/src/app/[locale]/boards/(content)/_client.module.css index 158ad16ae..d0f0252e6 100644 --- a/apps/nextjs/src/app/[locale]/boards/(content)/_client.module.css +++ b/apps/nextjs/src/app/[locale]/boards/(content)/_client.module.css @@ -9,14 +9,46 @@ } .gutter { - position: relative; - top: 0; + --board-gutter-sticky-top: calc((var(--app-shell-header-offset, 0px) + 1rem) * var(--board-canvas-inverse-scale, 1)); + --board-gutter-viewport-height: calc( + (100dvh - var(--app-shell-header-offset, 0px) - 1rem) * var(--board-canvas-inverse-scale, 1) + ); + + position: sticky; + top: var(--board-gutter-sticky-top); align-self: start; + box-sizing: border-box; + height: var(--board-gutter-viewport-height); padding-top: 24px; margin-top: -24px; - max-height: calc(100dvh - var(--app-shell-header-offset, 0px) - var(--mantine-spacing-md)); overflow-y: auto; overscroll-behavior: contain; scrollbar-gutter: stable; - transform: translateY(var(--board-gutter-sticky-offset, 0px)); +} + +.gutter[data-board-editing="true"] { + outline: 1px dashed var(--mantine-color-default-border); + outline-offset: -1px; + border-radius: var(--mantine-radius-md); +} + +.gutter[data-board-editing="true"]::before { + position: sticky; + top: 0; + z-index: 2; + display: block; + width: fit-content; + height: 24px; + padding-inline: var(--mantine-spacing-xs); + margin-top: -24px; + overflow: hidden; + font-size: var(--mantine-font-size-xs); + line-height: 24px; + color: var(--mantine-color-dimmed); + text-overflow: ellipsis; + white-space: nowrap; + pointer-events: none; + content: attr(aria-label); + background: color-mix(in srgb, var(--mantine-color-body) 88%, transparent); + border-radius: var(--mantine-radius-sm); } diff --git a/e2e/board-grid.spec.ts b/e2e/board-grid.spec.ts index 512fddf08..4a16065bb 100644 --- a/e2e/board-grid.spec.ts +++ b/e2e/board-grid.spec.ts @@ -245,6 +245,14 @@ describe("Board grid", () => { await expect(page.locator(`[data-grid-runtime="${gridRuntimeMarker}"]`)).toHaveCount(3); await expect(page.getByTestId("board-grid-editor-loading")).toHaveCount(0); await expect(page.getByTestId("board-canvas-row-count-button")).toHaveCount(0); + await expect(rail).toHaveAttribute("data-board-editing", "true"); + await expect(rail).toHaveCSS("position", "sticky"); + await expect(rail).toHaveCSS("transform", "none"); + const railBox = await expectBoundingBoxAsync(rail); + expect(railBox.height + railBox.y).toBeCloseTo(page.viewportSize()?.height ?? 0, 0); + expect(await rail.evaluate((element) => getComputedStyle(element, "::before").content.replaceAll('"', ""))).toBe( + "Left dashboard rail", + ); await expect(logicalTile).toHaveCSS("overflow-x", "hidden"); await expect(logicalTile).toHaveCSS("overflow-y", "auto"); await logicalTile.evaluate((element) => {