From fef83b3bf244a9bf3cb4afa75dbc433d8725014f Mon Sep 17 00:00:00 2001 From: Tudor Date: Wed, 15 Jul 2026 12:32:36 +0100 Subject: [PATCH] fix(compare): sticky school bar hidden behind the site header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Navigation header is position:sticky top:0 (z-index 1000). The school bar was also sticky top:0 (z-index 10), so when scrolled it pinned at the same top:0 *behind* the header — on mobile 57 of its 72px were covered, leaving only a sliver, so you couldn't see which schools were selected. Offset the bar's sticky top to the header height (65px desktop, 57px mobile — the Navigation breakpoint is also 640px) so it pins just below. e2e guard asserts the bar's sticky offset is at least the header height (verified it fails against the pre-fix build). Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_0146VHeLAWjDVE2B5uU67jCB --- e2e/tests/journeys.spec.ts | 13 +++++++++++++ nextjs-app/components/ComparisonView.module.css | 11 +++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/e2e/tests/journeys.spec.ts b/e2e/tests/journeys.spec.ts index d4cc865..6ae1d16 100644 --- a/e2e/tests/journeys.spec.ts +++ b/e2e/tests/journeys.spec.ts @@ -227,6 +227,19 @@ test('compare chart on mobile shows school chips with tap-to-focus', async ({ pa ); expect(bodyOverflowsX).toBe(false); + // The sticky school bar must pin *below* the sticky site header, not at + // top:0 where the header covers it and the selected schools are hidden. + // Assert the sticky offset directly (robust — no scroll timing needed). + const barTop = await page + .locator('[class*="schoolBar"]') + .first() + .evaluate((el) => parseFloat(getComputedStyle(el).top)); + const headerHeight = await page + .locator('[class*="header"]') + .first() + .evaluate((el) => el.getBoundingClientRect().height); + expect(barTop).toBeGreaterThanOrEqual(headerHeight - 1); + // The trends chart still renders (inside the Explore trends section)… const chartCanvas = page.locator('canvas:visible').first(); await expect(chartCanvas).toBeVisible({ timeout: 15_000 }); diff --git a/nextjs-app/components/ComparisonView.module.css b/nextjs-app/components/ComparisonView.module.css index 8ea0615..4b301e4 100644 --- a/nextjs-app/components/ComparisonView.module.css +++ b/nextjs-app/components/ComparisonView.module.css @@ -80,10 +80,12 @@ } /* Sticky school bar — column identity while scrolling; horizontal scroll on - narrow screens */ + narrow screens. Offset by the sticky site header's height (Navigation is + position: sticky, top: 0) so this bar pins just below it instead of + sliding underneath and being hidden. Header ≈ 65px desktop / 57px mobile. */ .schoolBar { position: sticky; - top: 0; + top: 65px; z-index: 10; background: var(--bg-primary, #faf7f2); display: flex; @@ -173,6 +175,11 @@ pills with short names (matching the mobile mockup) instead of full-width cards whose names wrap to several lines. */ @media (max-width: 640px) { + /* The mobile Navigation header is shorter (≈57px). */ + .schoolBar { + top: 57px; + } + .schoolChip { flex: 0 0 auto; min-width: 0; -- 2.54.0