fix(detail): restore the shell's mobile header/nav CSS
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m6s
PR Checks / Backend Smoke (pull_request) Successful in 8s
PR Checks / Build Backend (no push) (pull_request) Successful in 36s
PR Checks / Build Frontend (no push) (pull_request) Successful in 46s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 1m19s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 9s

The server/client split moved the header and sticky nav markup into
SchoolDetailShell, but their responsive rules stayed behind in
schoolSections.module.css. CSS Modules hash class names per file, so those
rules stopped matching entirely: on mobile the header details block never
collapsed ("Show all details" e2e journey failed), the toggle itself never
appeared, and the section-nav mobile swap (menu button in, link row out)
never applied.

Ports the stranded blocks into SchoolDetailShell.module.css verbatim: the
768px header block (stacked header, wrapped meta pills, details toggle +
collapse) and the 640px section-nav blocks (scroll-fade mask, bottom-sheet
panel, control swap). Adds a jest guard that every class a components/school
component references is defined in the stylesheet that component imports —
it fails on the three classes that had no rule at all here
(headerDetailsOpen, atEnd, sectionNavBackLabel).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Tudor
2026-08-06 10:31:12 +01:00
co-authored by Claude Opus 5
parent 803e68970c
commit e098ad4bd1
2 changed files with 142 additions and 1 deletions
@@ -662,8 +662,106 @@
}
@media (max-width: 640px) {
.sectionNavAll {
min-height: 36px;
}
}
@media (max-width: 768px) {
.headerContent {
flex-direction: column;
gap: 1rem;
}
.actions {
width: 100%;
}
.btnAdd,
.btnRemove {
flex: 1;
}
.schoolName {
font-size: 1.25rem;
word-break: break-word;
}
/* Pills wrap horizontally instead of stacking — short tokens like
"Manchester" / "Voluntary aided" fit 2 per row instead of 3 full
rows of empty horizontal space. */
.meta {
flex-direction: row;
flex-wrap: wrap;
gap: 0.375rem;
}
/* Secondary header info (headteacher, website, pupil count, trust,
contact, area) isn't needed above the fold on phones/tablets, so it's
collapsed by default and revealed on demand via the "Show all details"
link — reclaiming the vertical space so the metrics surface sooner. */
.detailsToggle {
display: inline-flex;
}
.headerDetails {
display: none;
}
.headerDetailsOpen {
display: flex;
flex-direction: column;
gap: 0.375rem;
}
}
@media (max-width: 640px) {
.sectionNavLinks {
-webkit-mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent);
mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent);
}
/* When scrolled to the end, drop the fade so the last item isn't dimmed. */
.sectionNavLinks.atEnd {
-webkit-mask-image: none;
mask-image: none;
}
.sectionsPanel {
position: fixed;
top: auto;
left: 0;
right: 0;
bottom: 0;
width: auto;
max-height: 74vh;
border-radius: 16px 16px 0 0;
padding: 0.5rem 0.6rem calc(0.8rem + env(safe-area-inset-bottom, 0));
box-shadow: 0 -10px 40px rgba(26, 22, 18, 0.25);
}
.sectionsItem {
padding: 0.7rem 0.6rem;
font-size: 0.9rem;
}
}
/* Swap which controls show at the mobile breakpoint. Declared last so these
display rules win over the base (equal-specificity) declarations above. */
@media (max-width: 640px) {
.sectionNavLinks,
.sectionNavCompare,
.sectionNavAll,
.sectionNavBackLabel {
display: none;
}
.sectionNavMenu {
display: flex;
}
.sectionNavCompareIcon {
display: inline-flex;
}
}