From 4043270a77bbe4edb18207fa5f1d94d4747fe12f Mon Sep 17 00:00:00 2001 From: Tudor Date: Fri, 14 Aug 2026 22:59:12 +0100 Subject: [PATCH] fix(home): stop implying we are official, and fix the mobile hero and search MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three things, all reported from the live mobile view. WE ARE NOT AN OFFICIAL SERVICE The value prop read "Official & trusted", whose grammatical subject is this site — it reads as a claim that schoolcompare is an official service. It is not; it is an independent site that republishes official figures. Now "Built on official data", which describes the data instead. Checked every other use of the word: all nine describe the data ("official DfE figures", "the official figure isn't in") and are correct as they stand. That one title was the only place the site described itself. The footer now says it outright — "An independent site. Not affiliated with the Department for Education or Ofsted." — so it appears on every page rather than being left to inference. An e2e test asserts both halves: that the statement is present, and that no text presents the site itself as official. The disclaimer first measured 4.71:1 against a 4.5 floor. That is a fine margin for decoration and the wrong one for a line whose job is to be legible to someone checking whether this is a government site; it is now 5.59:1, quieter than the copy around it by size rather than by contrast. THE ARTWORK SAT UNDER THE SEARCH ON PHONES The DOM keeps .heroContent first so the desktop overlay does not depend on source order, which left the band stranded at the bottom of the panel, reading as a strip stuck on the end rather than a hero image. `order` moves it above the copy on phones; it is decorative and aria-hidden, so no reading order changes. Measured on a 667px viewport — the shortest phone still in use — the search button lands at 418px, comfortably inside the fold. THE SEARCH INPUT WAS UNUSABLE ON PHONES "Search schools" is a fixed 134px with white-space: nowrap, so it took 48% of the row. Measured on staging: 390px input text space 102px placeholder needs 194px 360px 72px 320px 32px At 320px you could not see what you were typing. The button now wraps to its own full-width row below 480px, which fixes 360px and up — 390px goes from 102px to 226px of text space. The pill stays a single element, so it keeps its border, shadow and :focus-within ring, and the button gains a full-width tap target. 320px is still ~30px short. Closing it needs a shorter placeholder, which three other tests match on by exact string; left alone deliberately rather than churn them for a width that is effectively gone. Co-Authored-By: Claude Opus 5 --- e2e/tests/journeys.spec.ts | 27 ++++++++++++++++++++++ nextjs-app/components/FilterBar.module.css | 24 +++++++++++++++++++ nextjs-app/components/Footer.module.css | 16 +++++++++++++ nextjs-app/components/Footer.tsx | 8 +++++++ nextjs-app/components/HomeView.module.css | 20 +++++++++++++++- nextjs-app/components/HomeView.tsx | 15 +++++++++++- 6 files changed, 108 insertions(+), 2 deletions(-) diff --git a/e2e/tests/journeys.spec.ts b/e2e/tests/journeys.spec.ts index 07dfe10..ae31757 100644 --- a/e2e/tests/journeys.spec.ts +++ b/e2e/tests/journeys.spec.ts @@ -121,6 +121,33 @@ test('the home page has a real title', async ({ page }) => { expect(await page.title()).toMatch(/schoolcompare/i); }); +test('the site states its independence and never claims to be official', async ({ page }) => { + await page.goto('/'); + + // Carried in the footer, so it appears on every page rather than only here. + await expect( + page.getByText(/an independent site\.\s*not affiliated with the department for education/i) + ).toBeVisible(); + + /* + * Describing the DATA as official is accurate and appears throughout + * ("official DfE figures", "the official figure isn't in"). Describing the + * SITE as official is not: schoolcompare republishes government data, it is + * not a government service. The difference is the grammatical subject, so + * this looks for text that opens with "Official" as a standalone label — + * the shape a value-prop title or heading takes, and the shape the old + * "Official & trusted" took. + */ + const claims = await page.evaluate(() => + [...document.querySelectorAll('body *')] + .flatMap(el => [...el.childNodes] + .filter(n => n.nodeType === 3) + .map(n => (n.textContent ?? '').trim())) + .filter(t => /^Official\b/i.test(t) && !/^Official\s+(DfE|data|figures)/i.test(t)) + ); + expect(claims, `text presenting the site itself as official: ${claims.join(' | ')}`).toEqual([]); +}); + test('the landing bands share one vertical rhythm', async ({ page }) => { await page.goto('/'); const gaps = await page.evaluate(() => { diff --git a/nextjs-app/components/FilterBar.module.css b/nextjs-app/components/FilterBar.module.css index 8a085b2..c062e4a 100644 --- a/nextjs-app/components/FilterBar.module.css +++ b/nextjs-app/components/FilterBar.module.css @@ -460,6 +460,30 @@ } } +/* + * Narrow phones: the button drops below the input instead of sharing the row. + * + * "Search schools" is a fixed 134px with `white-space: nowrap`, so on a 390px + * screen it took 48% of the row and left the input 102px of text space for a + * 194px placeholder — the field showed "School name or" and stopped. At 320px + * the input was down to 32px, which is too narrow to read what you are typing. + * + * Wrapping rather than restructuring: the pill stays one element, so it keeps + * its border, shadow and :focus-within ring, and the button gets a full-width + * tap target on the way. Giving the button a 100% flex-basis is what forces + * the wrap; the input keeps `flex: 1` and so takes the whole first row. + */ +@media (max-width: 480px) { + .heroMode .omniBoxContainer { + flex-wrap: wrap; + gap: 0.5rem; + } + .heroMode .searchButton { + flex: 1 1 100%; + width: 100%; + } +} + @media (max-width: 420px) { /* Below this the pin costs more room than it earns. */ .heroMode .omniIcon { diff --git a/nextjs-app/components/Footer.module.css b/nextjs-app/components/Footer.module.css index 53ebe8d..c085ff2 100644 --- a/nextjs-app/components/Footer.module.css +++ b/nextjs-app/components/Footer.module.css @@ -92,6 +92,22 @@ max-width: 34ch; } +/* + * Quieter than .description, but by size only — not by contrast. + * + * --on-sunken-faint measured 4.71:1 here, which clears AA by 0.21. That is a + * fine margin for decorative text and the wrong one for a disclaimer, whose + * whole job is to be legible to someone checking whether this is a government + * site. --on-sunken-muted is 5.66:1 on the same band. + */ +.independence { + margin: 0; + font-size: var(--step--2); + line-height: 1.6; + color: var(--on-sunken-muted); + max-width: 38ch; +} + .sectionTitle { margin: 0; font-family: var(--font-display); diff --git a/nextjs-app/components/Footer.tsx b/nextjs-app/components/Footer.tsx index aa6a8c6..8267979 100644 --- a/nextjs-app/components/Footer.tsx +++ b/nextjs-app/components/Footer.tsx @@ -35,6 +35,14 @@ export function Footer() {

Compare primary and secondary schools across England.

+ {/* + Says once, plainly, what the landing page's value props only + imply: we publish official data, we are not an official body. + Cheap to state and expensive to be wrong about. + */} +

+ An independent site. Not affiliated with the Department for Education or Ofsted. +

, tintClass: styles.propIconTrust, - title: 'Official & trusted', + /* + * "Built on official data", never "Official". + * + * The previous title was "Official & trusted", whose grammatical subject + * is this site — it reads as a claim that schoolcompare is itself an + * official service. It is not: it is an independent site that republishes + * official figures. The distinction is the difference between describing + * the data and describing ourselves, and only the first is true. + * + * Everywhere else the word appears ("official DfE figures", "the official + * figure isn't in") it already qualifies the data, which is correct and + * should stay. + */ + title: 'Built on official data', body: 'Every figure comes from DfE performance tables and Ofsted.', }, {