feat(detail): move religious character into header details + mobile reveal #83
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -99,6 +99,9 @@ export function SchoolDetailView({
|
||||
const heroMapRef = useRef<SchoolHeroMapHandle>(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 && (
|
||||
<span className={styles.metaItem}>{formatAgeRange(schoolInfo.age_range)}</span>
|
||||
)}
|
||||
{schoolInfo.religious_denomination && (
|
||||
<span className={styles.metaItem}>
|
||||
{['Does not apply', 'None'].includes(schoolInfo.religious_denomination)
|
||||
? 'None'
|
||||
: schoolInfo.religious_denomination}
|
||||
</span>
|
||||
)}
|
||||
{schoolInfo.nursery_provision && (
|
||||
<span className={styles.metaItem}>Nursery</span>
|
||||
)}
|
||||
@@ -391,7 +387,20 @@ export function SchoolDetailView({
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
<div className={styles.headerDetails}>
|
||||
<button
|
||||
type="button"
|
||||
className={styles.detailsToggle}
|
||||
aria-expanded={detailsOpen}
|
||||
aria-controls="school-header-details"
|
||||
onClick={() => setDetailsOpen((o) => !o)}
|
||||
>
|
||||
{detailsOpen ? 'Hide details' : 'Show all details'}
|
||||
<span aria-hidden="true">{detailsOpen ? '▴' : '▾'}</span>
|
||||
</button>
|
||||
<div
|
||||
id="school-header-details"
|
||||
className={`${styles.headerDetails}${detailsOpen ? ` ${styles.headerDetailsOpen}` : ''}`}
|
||||
>
|
||||
{schoolInfo.headteacher_name && (
|
||||
<span className={styles.headerDetail}>
|
||||
<strong>Headteacher:</strong> {schoolInfo.headteacher_name}
|
||||
@@ -433,6 +442,14 @@ export function SchoolDetailView({
|
||||
</a>
|
||||
</span>
|
||||
)}
|
||||
{schoolInfo.religious_denomination && (
|
||||
<span className={styles.headerDetail}>
|
||||
<strong>Religious character:</strong>{' '}
|
||||
{['Does not apply', 'None'].includes(schoolInfo.religious_denomination)
|
||||
? 'None'
|
||||
: schoolInfo.religious_denomination}
|
||||
</span>
|
||||
)}
|
||||
{schoolInfo.county && (
|
||||
<span className={styles.headerDetail}>
|
||||
<strong>County:</strong> {schoolInfo.county}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -83,6 +83,8 @@ export function SecondarySchoolDetailView({
|
||||
const isInComparison = isSelected(schoolInfo.urn);
|
||||
|
||||
const [activeSection, setActiveSection] = useState<string>('');
|
||||
// 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 && (
|
||||
<span className={styles.badge}>{formatAgeRange(schoolInfo.age_range)}</span>
|
||||
)}
|
||||
{schoolInfo.religious_denomination && (
|
||||
<span className={styles.badge}>
|
||||
{['Does not apply', 'None'].includes(schoolInfo.religious_denomination)
|
||||
? 'None'
|
||||
: schoolInfo.religious_denomination}
|
||||
</span>
|
||||
)}
|
||||
{schoolInfo.nursery_provision && (
|
||||
<span className={styles.badge}>Nursery</span>
|
||||
)}
|
||||
@@ -288,7 +283,20 @@ export function SecondarySchoolDetailView({
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
<div className={styles.headerDetails}>
|
||||
<button
|
||||
type="button"
|
||||
className={styles.detailsToggle}
|
||||
aria-expanded={detailsOpen}
|
||||
aria-controls="school-header-details"
|
||||
onClick={() => setDetailsOpen((o) => !o)}
|
||||
>
|
||||
{detailsOpen ? 'Hide details' : 'Show all details'}
|
||||
<span aria-hidden="true">{detailsOpen ? '▴' : '▾'}</span>
|
||||
</button>
|
||||
<div
|
||||
id="school-header-details"
|
||||
className={`${styles.headerDetails}${detailsOpen ? ` ${styles.headerDetailsOpen}` : ''}`}
|
||||
>
|
||||
{schoolInfo.headteacher_name && (
|
||||
<span className={styles.headerDetail}>
|
||||
<strong>Headteacher:</strong> {schoolInfo.headteacher_name}
|
||||
@@ -326,6 +334,14 @@ export function SecondarySchoolDetailView({
|
||||
</a>
|
||||
</span>
|
||||
)}
|
||||
{schoolInfo.religious_denomination && (
|
||||
<span className={styles.headerDetail}>
|
||||
<strong>Religious character:</strong>{' '}
|
||||
{['Does not apply', 'None'].includes(schoolInfo.religious_denomination)
|
||||
? 'None'
|
||||
: schoolInfo.religious_denomination}
|
||||
</span>
|
||||
)}
|
||||
{schoolInfo.county && (
|
||||
<span className={styles.headerDetail}>
|
||||
<strong>County:</strong> {schoolInfo.county}
|
||||
|
||||
Reference in New Issue
Block a user