diff --git a/e2e/tests/journeys.spec.ts b/e2e/tests/journeys.spec.ts index 29aa4e3..80178a6 100644 --- a/e2e/tests/journeys.spec.ts +++ b/e2e/tests/journeys.spec.ts @@ -148,6 +148,24 @@ test('school detail page shows GIAS identity/contact details and drops the unwir } }); +test('header details collapse behind a "Show all details" toggle on mobile', async ({ page }) => { + await page.setViewportSize({ width: 390, height: 844 }); + const [urn] = await twoPrimaryUrns(page); + await page.goto(`/school/${urn}`); + await expect(page.locator('h1').first()).toBeVisible({ timeout: 15_000 }); + + // Collapsed by default on mobile/tablet … + const details = page.locator('#school-header-details'); + await expect(details).toBeHidden(); + const toggle = page.getByRole('button', { name: /show all details/i }); + await expect(toggle).toBeVisible(); + + // … and the link reveals them (label flips to "Hide details"). + await toggle.click(); + await expect(details).toBeVisible(); + await expect(page.getByRole('button', { name: /hide details/i })).toBeVisible(); +}); + test('a report-card school shows its report card, dated to the report-card inspection', async ({ page }) => { // Detail views detected report cards via `framework`, which the API never // sets to "ReportCard" — so report-card schools rendered as legacy ratings diff --git a/nextjs-app/components/SchoolDetailView.module.css b/nextjs-app/components/SchoolDetailView.module.css index 0ea36c2..5286103 100644 --- a/nextjs-app/components/SchoolDetailView.module.css +++ b/nextjs-app/components/SchoolDetailView.module.css @@ -197,6 +197,22 @@ text-decoration: underline; } +/* "Show all details" reveal — only rendered on mobile/tablet, where the + header details block is collapsed below the fold. Hidden on desktop. */ +.detailsToggle { + display: none; + align-items: center; + gap: 0.25rem; + margin-top: 0.5rem; + padding: 0; + background: none; + border: none; + font-size: 0.8125rem; + font-weight: 600; + color: var(--accent-teal, #2d7d7d); + cursor: pointer; +} + /* Gender split card — sits in the Pupils & Inclusion heroStatGrid */ .genderSplitValue { display: flex; @@ -1205,14 +1221,24 @@ gap: 0.375rem; } - /* Secondary header info (headteacher, website, pupil count, trust) - isn't needed above the fold on phones — pupil count lives in the - Pupils & Inclusion section, website is one scroll away. Reclaim - the ~3 vertical lines so the actual metrics surface sooner. */ + /* 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; + } + .metricsGrid { grid-template-columns: repeat(2, 1fr); } diff --git a/nextjs-app/components/SchoolDetailView.tsx b/nextjs-app/components/SchoolDetailView.tsx index adca63c..3a14cc7 100644 --- a/nextjs-app/components/SchoolDetailView.tsx +++ b/nextjs-app/components/SchoolDetailView.tsx @@ -99,6 +99,9 @@ export function SchoolDetailView({ const heroMapRef = useRef(null); // "All ▾" jump menu listing every section. const [sectionsOpen, setSectionsOpen] = useState(false); + // Header details (headteacher, contact, trust, area) collapse behind a + // "Show all details" link on mobile/tablet, where they're below the fold. + const [detailsOpen, setDetailsOpen] = useState(false); // Back returns to wherever the user came from; deep-links (no in-app history) // fall back to search so the button never dead-ends or leaves the site. @@ -354,13 +357,6 @@ export function SchoolDetailView({ {schoolInfo.age_range && ( {formatAgeRange(schoolInfo.age_range)} )} - {schoolInfo.religious_denomination && ( - - {['Does not apply', 'None'].includes(schoolInfo.religious_denomination) - ? 'None' - : schoolInfo.religious_denomination} - - )} {schoolInfo.nursery_provision && ( Nursery )} @@ -391,7 +387,20 @@ export function SchoolDetailView({ )}

)} -
+ +
{schoolInfo.headteacher_name && ( Headteacher: {schoolInfo.headteacher_name} @@ -433,6 +442,14 @@ export function SchoolDetailView({ )} + {schoolInfo.religious_denomination && ( + + Religious character:{' '} + {['Does not apply', 'None'].includes(schoolInfo.religious_denomination) + ? 'None' + : schoolInfo.religious_denomination} + + )} {schoolInfo.county && ( County: {schoolInfo.county} diff --git a/nextjs-app/components/SecondarySchoolDetailView.module.css b/nextjs-app/components/SecondarySchoolDetailView.module.css index a4f02e0..cf57443 100644 --- a/nextjs-app/components/SecondarySchoolDetailView.module.css +++ b/nextjs-app/components/SecondarySchoolDetailView.module.css @@ -207,6 +207,22 @@ text-decoration: underline; } +/* "Show all details" reveal — only rendered on mobile/tablet, where the + header details block is collapsed below the fold. Hidden on desktop. */ +.detailsToggle { + display: none; + align-items: center; + gap: 0.25rem; + margin-top: 0.5rem; + padding: 0; + background: none; + border: none; + font-size: 0.8125rem; + font-weight: 600; + color: var(--accent-teal, #2d7d7d); + cursor: pointer; +} + .actions { display: flex; gap: 0.5rem; @@ -1066,7 +1082,18 @@ padding: 0.1rem 0.375rem; } + /* Collapsed below the fold on phones/tablets; revealed via "Show all + details" so the metrics surface sooner. */ + .detailsToggle { + display: inline-flex; + } + .headerDetails { + display: none; + } + + .headerDetailsOpen { + display: flex; flex-direction: column; gap: 0.375rem; } diff --git a/nextjs-app/components/SecondarySchoolDetailView.tsx b/nextjs-app/components/SecondarySchoolDetailView.tsx index 1304a36..dedd252 100644 --- a/nextjs-app/components/SecondarySchoolDetailView.tsx +++ b/nextjs-app/components/SecondarySchoolDetailView.tsx @@ -83,6 +83,8 @@ export function SecondarySchoolDetailView({ const isInComparison = isSelected(schoolInfo.urn); const [activeSection, setActiveSection] = useState(''); + // Header details collapse behind a "Show all details" link on mobile/tablet. + const [detailsOpen, setDetailsOpen] = useState(false); const latestResults = yearlyData.length > 0 ? yearlyData[yearlyData.length - 1] : null; @@ -246,13 +248,6 @@ export function SecondarySchoolDetailView({ {schoolInfo.age_range && ( {formatAgeRange(schoolInfo.age_range)} )} - {schoolInfo.religious_denomination && ( - - {['Does not apply', 'None'].includes(schoolInfo.religious_denomination) - ? 'None' - : schoolInfo.religious_denomination} - - )} {schoolInfo.nursery_provision && ( Nursery )} @@ -288,7 +283,20 @@ export function SecondarySchoolDetailView({ )}

)} -
+ +
{schoolInfo.headteacher_name && ( Headteacher: {schoolInfo.headteacher_name} @@ -326,6 +334,14 @@ export function SecondarySchoolDetailView({ )} + {schoolInfo.religious_denomination && ( + + Religious character:{' '} + {['Does not apply', 'None'].includes(schoolInfo.religious_denomination) + ? 'None' + : schoolInfo.religious_denomination} + + )} {schoolInfo.county && ( County: {schoolInfo.county}