fix(admissions): move the cut-off detail into its own section #103

Merged
tudor merged 1 commits from fix/admissions-section-height into main 2026-08-20 14:03:02 +00:00
Owner

Reported on Our Lady Queen of Heaven: the Admissions card is enormous and pushes everything else down.

Measured on that page, it was not an impression — Admissions was half the height of every section put together:

admissions   1503px  50.5%  #####################################
history       528px  17.7%  #############
results       526px  17.7%  #############
inclusion     215px   7.2%  #####
ofsted        203px   6.8%  #####

Cause — a layout trick meeting content it was never sized for

The admissions views are stacked in one grid cell so switching them never shifts layout, and the hidden ones keep their box (display: block; visibility: hidden). That works while the views are comparable in height.

The distance view I added in #102 carries a chart, a table and a map. It measured 1402px against the tile grid's 316px, so it sized the grid row and pinned every other view to its height — including the one that renders by default. The result was four tiles adrift in ~1080px of blank card, on a view nobody had clicked.

My regression, introduced in #102.

Fix — the detail moves out, rather than only unpinning it

Every other topic on the page is a section with a nav entry. "How close did we need to live, and would we have got in?" is a topic, not a variant reading of the intake figures — putting it in a tab inside Admissions is what made Admissions three times everything else. The headline number stays on the Admissions tile where the intake story is; the record behind it moves to a Distance section directly below, with its own nav entry.

admissions   1503px -> 554px
distance        new -> 743px     (median section ~528px)

Three further changes, each better as well as shorter

The map renders on request. Before a postcode is entered it is a circle drawn round a school, and it costs a Leaflet bundle and 240px of height to say that. A successful check opens it automatically — the point at which it starts answering something, since it then shows your home against the rings. Map height 320px → 240px.

The chart appears only at four published years — the same threshold that lets the summary state a direction. Below that we already refuse to call the series a trend, and a line through three points asserts one regardless of what the sentence beneath it admits. The table carries those years anyway, with the reasons a line cannot show. (The reported school has 3 years, so it gets the table and no chart.)

Three caveat paragraphs become one. They said walking-route twice and made the same point about priorities in two voices, for ~180px. The merged one sits in CutoffDistanceDetail rather than inside the check, so it still renders for a school with missing coordinates — where there is a table but no map and no check. Every claim is preserved; I listed them in the constant's docblock so a future trim can see what is load-bearing.

Also dropped a now-vestigial "Where the last place went" heading: it introduced a map that had moved behind a button, and echoed the section title directly above it.

The guard, and the version of it that proved nothing

The new e2e test asserts no section exceeds 2.5× the median section height — the reader's actual complaint, one section wildly out of proportion with its neighbours.

Measuring the card's internals cannot catch this. The tile grid is flex: 1, so it absorbs the stretch and every box still measures full; my first attempt compared a view's height to the sum of its children and reported 34px of slack on a page that was visibly broken.

The first working version then targeted an arbitrary primary via twoPrimaryUrns — and passed against the live bug, because a school with no cut-off history has no third view to do the padding. Pointed at a school that actually holds the history, it fails on staging with the diagnosis in the message:

#admissions is 1459px against a 526px median:
  ofsted=201, results=526, admissions=1459, inclusion=215, history=528
Expected: < 2.5   Received: 2.77

Verification

  • tsc clean; next build green
  • 218 frontend tests, 54 backend — including new assertions that the chart only appears with 4+ points, that the caveat renders exactly once, and that the map stays behind a request until asked for or answered
  • Rendered offline against the real compiled CSS in both themes and at 390px; no horizontal page scroll, heading order well-formed after the h4 → h3 promotion

e2e against staging: 48 of 54 pass. The 6 failures are expected and are the point — 5 assert #distance exists and staging still serves the pre-change build where it was a tab, and the 6th is the proportion guard failing on the live bug. All 6 should go green on deploy; worth confirming that rather than taking my word for it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WDvkyqqHABm4bmth2kjAxE

Reported on [Our Lady Queen of Heaven](https://stx.schoolcompare.co.uk/school/101051-our-lady-queen-of-heaven-rc-school): the Admissions card is enormous and pushes everything else down. Measured on that page, it was not an impression — Admissions was **half the height of every section put together**: ``` admissions 1503px 50.5% ##################################### history 528px 17.7% ############# results 526px 17.7% ############# inclusion 215px 7.2% ##### ofsted 203px 6.8% ##### ``` ## Cause — a layout trick meeting content it was never sized for The admissions views are stacked in one grid cell so switching them never shifts layout, and the hidden ones **keep their box** (`display: block; visibility: hidden`). That works while the views are comparable in height. The distance view I added in #102 carries a chart, a table and a map. It measured **1402px against the tile grid's 316px**, so it sized the grid row and pinned every other view to its height — including the one that renders by default. The result was four tiles adrift in ~1080px of blank card, on a view nobody had clicked. My regression, introduced in #102. ## Fix — the detail moves out, rather than only unpinning it Every other topic on the page is a section with a nav entry. "How close did we need to live, and would we have got in?" is a *topic*, not a variant reading of the intake figures — putting it in a tab inside Admissions is what made Admissions three times everything else. The headline number stays on the Admissions tile where the intake story is; the record behind it moves to a **Distance** section directly below, with its own nav entry. ``` admissions 1503px -> 554px distance new -> 743px (median section ~528px) ``` ## Three further changes, each better as well as shorter **The map renders on request.** Before a postcode is entered it is a circle drawn round a school, and it costs a Leaflet bundle and 240px of height to say that. A successful check opens it automatically — the point at which it starts answering something, since it then shows your home against the rings. Map height 320px → 240px. **The chart appears only at four published years** — the same threshold that lets the summary state a direction. Below that we already refuse to call the series a trend, and a line through three points asserts one regardless of what the sentence beneath it admits. The table carries those years anyway, with the reasons a line cannot show. (The reported school has 3 years, so it gets the table and no chart.) **Three caveat paragraphs become one.** They said walking-route twice and made the same point about priorities in two voices, for ~180px. The merged one sits in `CutoffDistanceDetail` rather than inside the check, so it still renders for a school with missing coordinates — where there is a table but no map and no check. Every claim is preserved; I listed them in the constant's docblock so a future trim can see what is load-bearing. Also dropped a now-vestigial "Where the last place went" heading: it introduced a map that had moved behind a button, and echoed the section title directly above it. ## The guard, and the version of it that proved nothing The new e2e test asserts **no section exceeds 2.5× the median section height** — the reader's actual complaint, one section wildly out of proportion with its neighbours. Measuring the card's internals cannot catch this. The tile grid is `flex: 1`, so it absorbs the stretch and every box still measures full; my first attempt compared a view's height to the sum of its children and reported 34px of slack on a page that was visibly broken. The first working version then targeted an arbitrary primary via `twoPrimaryUrns` — and **passed against the live bug**, because a school with no cut-off history has no third view to do the padding. Pointed at a school that actually holds the history, it fails on staging with the diagnosis in the message: ``` #admissions is 1459px against a 526px median: ofsted=201, results=526, admissions=1459, inclusion=215, history=528 Expected: < 2.5 Received: 2.77 ``` ## Verification - `tsc` clean; `next build` green - **218 frontend tests**, **54 backend** — including new assertions that the chart only appears with 4+ points, that the caveat renders exactly once, and that the map stays behind a request until asked for or answered - Rendered offline against the real compiled CSS in both themes and at 390px; no horizontal page scroll, heading order well-formed after the h4 → h3 promotion **e2e against staging: 48 of 54 pass.** The 6 failures are expected and are the point — 5 assert `#distance` exists and staging still serves the pre-change build where it was a tab, and the 6th is the proportion guard failing on the live bug. All 6 should go green on deploy; worth confirming that rather than taking my word for it. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01WDvkyqqHABm4bmth2kjAxE
tudor added 1 commit 2026-08-20 13:54:40 +00:00
fix(admissions): move the cut-off detail into its own section
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m5s
PR Checks / Backend Smoke (pull_request) Successful in 8s
PR Checks / Build Backend (no push) (pull_request) Successful in 13s
PR Checks / Build Frontend (no push) (pull_request) Successful in 45s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 11s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 1m59s
94151c58ea
The admissions card measured 1503px on a live school page — half the height
of every section put together, and nearly three times the next largest — with
its default view rendering as four tiles adrift in about 1080px of blank card.

The cause was a layout trick meeting content it was never sized for. The
admissions views are stacked in one grid cell so switching them never shifts
layout, and the hidden ones keep their box: only visibility is dropped. That
works while the views are comparable. The distance view added in #102 carries
a chart, a table and a map, came to 1402px against the tile grid's 316px, and
pinned every other view to its height — including the one that renders by
default, which nobody had clicked.

Rather than only unpinning it, the detail moves out. Every other topic on the
page is a section with a nav entry, and "how close did we need to live, and
would we have got in?" is a topic, not a variant reading of the intake
figures. The headline number stays on the Admissions tile where the intake
story is; the record behind it now lives in a Distance section directly below.

  admissions   1503px -> 554px
  distance        new -> 743px   (median section on the page is ~528px)

Three further changes, each of which also makes the content better rather
than only shorter:

  * The map renders on request. Before a postcode is entered it is a circle
    drawn round a school, and it costs a Leaflet bundle and 240px to say so;
    a successful check opens it automatically, which is the point at which it
    starts answering something. Map height 320px -> 240px.
  * The chart appears only at the four published years that let the summary
    state a direction. Below that we already refuse to call the series a
    trend, and a line through three points asserts one regardless of what the
    sentence beneath it admits. The table carries those years anyway, with
    the reasons a line cannot show.
  * Three caveat paragraphs become one. They said walking-route twice and
    made the same point about priorities in two voices. It now sits in
    CutoffDistanceDetail rather than inside the check, so it still renders
    for a school with coordinates missing, where there is a table but no map
    and no check.

The new e2e guard asserts no section exceeds 2.5x the median section height.
Measuring the card's internals cannot catch this: the tile grid is flex: 1,
so it absorbs the stretch and every box still looks full. The first version
of this test targeted an arbitrary primary, passed against the live bug, and
proved nothing; pointed at a school that actually holds cut-off history it
fails on staging with "#admissions is 1459px against a 526px median".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WDvkyqqHABm4bmth2kjAxE

🤖 AI Code Review (Claude Code)

This PR pulls the school-level cut-off distance detail (chart, table, map, postcode check) out of a tab inside the Admissions card into its own top-level 'Distance' section on both primary and secondary school pages, since the tall detail view was distorting the stacked-grid admissions card height. It also consolidates three separate caveat paragraphs into one, gates the trend chart on having 4+ published years (matching the existing trend-summary threshold), defers the Leaflet map behind a 'show on map' toggle, and updates e2e/unit tests accordingly. The refactor is internally consistent: the new hasCutoffDetail predicate is shared between the section components and the nav-builder functions so the sticky nav can't link to an unrendered anchor, prop threading through Primary/Secondary section components matches call sites, and no stale imports/exports (e.g. CUTOFF_MAP_CAVEAT, showCaveat) remain.

✅ No issues found.

## 🤖 AI Code Review (Claude Code) This PR pulls the school-level cut-off distance detail (chart, table, map, postcode check) out of a tab inside the Admissions card into its own top-level 'Distance' section on both primary and secondary school pages, since the tall detail view was distorting the stacked-grid admissions card height. It also consolidates three separate caveat paragraphs into one, gates the trend chart on having 4+ published years (matching the existing trend-summary threshold), defers the Leaflet map behind a 'show on map' toggle, and updates e2e/unit tests accordingly. The refactor is internally consistent: the new `hasCutoffDetail` predicate is shared between the section components and the nav-builder functions so the sticky nav can't link to an unrendered anchor, prop threading through Primary/Secondary section components matches call sites, and no stale imports/exports (e.g. `CUTOFF_MAP_CAVEAT`, `showCaveat`) remain. ✅ No issues found.
tudor merged commit 50b599a09b into main 2026-08-20 14:03:02 +00:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: tudor/school_compare#103