From 21a00f895a6d1f0c69b884ff104a8df29773bd24 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Sat, 31 Oct 2026 02:04:47 +0100 Subject: [PATCH] =?UTF-8?q?Answer=20stability=20round=201:=200=20?= =?UTF-8?q?=F0=9F=94=B4,=201=20=F0=9F=9F=A1=20(0=20misread);=20test=20the?= =?UTF-8?q?=20drawer=20opens=20and=20a=20link=20in=20it=20navigates,=20kee?= =?UTF-8?q?p=20the=20in-flow=20sidebar=20from=20stretching?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- e2e-tests/visual.spec.ts | 15 +++++++++++++++ public/css/styles.css | 11 ++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/e2e-tests/visual.spec.ts b/e2e-tests/visual.spec.ts index 4f6c164..3ef4363 100644 --- a/e2e-tests/visual.spec.ts +++ b/e2e-tests/visual.spec.ts @@ -148,6 +148,21 @@ test("mobile layout hides the sidebar off-canvas behind the hamburger", async ({ expect(offCanvas).toBe(true); }); +test("the hamburger opens the drawer over the scrim, and a link in it navigates", async ({ page }) => { + await page.setViewportSize({ width: 390, height: 844 }); + await page.goto("/dashboard"); + await page.locator(".hamburger").click(); + + const sidebar = page.locator(".sidebar"); + await expect(sidebar).toBeInViewport({ ratio: 1 }); + // A click is refused while the scrim sits above the drawer, which a lower z-index would cause. + await sidebar.locator("summary").first().click(); // the dashboard is the current page, so its links are in a folded branch + const link = sidebar.locator(".nav-children a.nav-self").first(); + const target = await link.getAttribute("href"); + await link.click(); + await expect(page).toHaveURL((url) => url.pathname === target?.split("?")[0]); +}); + test("Sign-out is a CSRF-guarded POST form: the token is issued on the page, a tokenless POST is refused", async ({ page }) => { await page.goto("/dashboard"); // The page issues a CSRF cookie and embeds the same token in the Sign-out form (double-submit). diff --git a/public/css/styles.css b/public/css/styles.css index 5385632..2b71a45 100644 --- a/public/css/styles.css +++ b/public/css/styles.css @@ -2,9 +2,6 @@ App Shell Template — pure HTML/CSS, no JavaScript ------------------------------------------------------------- Architecture - - Design tokens are two raw palettes picked by a theme block, so - the theme follows the system by default and can be forced - Light / Dark via radio + :has(). - Everything is a reusable "block": .nav-item, .filter, .chip, .badge, .btn, .menu, .table — combine freely. ============================================================= */ @@ -682,13 +679,13 @@ th[aria-sort="descending"] .sort-ico { transform: rotate(180deg); } /* ---------- 11. RESPONSIVE / HAMBURGER --------------------- */ .scrim { display: none; } -/* Off-canvas only where :has() works: without it nothing can read #nav-toggle, so the sidebar - stays in the flow above the content and the hamburger stays hidden. */ @media (max-width: 860px) { - .app { grid-template-columns: minmax(0, 1fr); } - .content { grid-column: 1; } + .app { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto 1fr; } + .content { grid-column: 1; grid-row: 2; } .search { min-width: 150px; flex: 1 1 auto; } + /* Off-canvas only where :has() works: without it nothing can read #nav-toggle, so the sidebar + stays in the flow above the content and the hamburger stays hidden. */ @supports selector(:has(a)) { .sidebar { position: fixed; inset: 0 auto 0 0; width: min(86vw, var(--nav-w));