From 8e0b7306297713ac597294adbdbf39043a8b54fc Mon Sep 17 00:00:00 2001 From: Tudor Date: Thu, 16 Jul 2026 21:05:16 +0100 Subject: [PATCH] fix(compare): align sticky school chips with their data columns on desktop The bar was a plain flex row while sections use a 200px-label + per-school grid, so chips drifted off the columns they label. The bar now shares the sections' grid template (via --school-count) at the same 761px breakpoint; verified pixel-exact against live section columns (236/615/994). Mobile pills unchanged. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_0146VHeLAWjDVE2B5uU67jCB --- e2e/tests/journeys.spec.ts | 8 +++++++ .../components/ComparisonView.module.css | 21 +++++++++++++++++++ nextjs-app/components/ComparisonView.tsx | 12 ++++++++--- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/e2e/tests/journeys.spec.ts b/e2e/tests/journeys.spec.ts index 9e26557..7b01cf7 100644 --- a/e2e/tests/journeys.spec.ts +++ b/e2e/tests/journeys.spec.ts @@ -197,6 +197,14 @@ test('comparing two schools shows the parent-first sections side by side', async // Every number gets an anchor: at least one England-average tick or label await expect(page.getByText(/England \d+/).first()).toBeVisible(); + // Desktop: the sticky school bar shares the sections' grid template + // (200px label rail + one column per school) so chips align with the + // columns they label. + const barTemplate = await page + .locator('[aria-label="Schools in this comparison"]') + .evaluate((el) => getComputedStyle(el).gridTemplateColumns); + expect(barTemplate).toMatch(/^200px /); + // Ofsted linkout goes to the school's provider page, never a report deep-link const ofstedLink = page.getByRole('link', { name: /Ofsted page/i }).first(); await expect(ofstedLink).toBeVisible(); diff --git a/nextjs-app/components/ComparisonView.module.css b/nextjs-app/components/ComparisonView.module.css index 4b301e4..d4de534 100644 --- a/nextjs-app/components/ComparisonView.module.css +++ b/nextjs-app/components/ComparisonView.module.css @@ -148,6 +148,27 @@ text-overflow: ellipsis; } +/* Desktop (matches the sections' 761px breakpoint): the bar adopts the same + grid template as compareSections' .grid — a 200px row-label rail plus one + column per school — so each chip sits exactly over the column it labels. + The first chip starts after the empty label rail. */ +@media (min-width: 761px) { + .schoolBar { + display: grid; + grid-template-columns: 200px repeat(var(--school-count, 3), 1fr); + gap: 0 0.75rem; + overflow-x: visible; + } + + .schoolChip { + min-width: 0; + } + + .schoolChip:first-child { + grid-column: 2; + } +} + .chipRemove { margin-left: auto; border: none; diff --git a/nextjs-app/components/ComparisonView.tsx b/nextjs-app/components/ComparisonView.tsx index fd42e1e..1733a5e 100644 --- a/nextjs-app/components/ComparisonView.tsx +++ b/nextjs-app/components/ComparisonView.tsx @@ -9,7 +9,7 @@ 'use client'; -import { useEffect, useRef, useState } from 'react'; +import { useEffect, useRef, useState, type CSSProperties } from 'react'; import { useRouter, usePathname, useSearchParams } from 'next/navigation'; import { useComparison } from '@/hooks/useComparison'; @@ -342,8 +342,14 @@ export function ComparisonView({ /> ) : ( <> - {/* Sticky school bar — column identity while scrolling */} -
+ {/* Sticky school bar — column identity while scrolling. On desktop + it shares the sections' grid template (via --school-count) so + each chip sits exactly over the column it labels. */} +
{activeSchools.map((school, index) => (