Files
school_compare/nextjs-app/components/Footer.tsx
T
Tudor b11ee3c8de
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m6s
PR Checks / Backend Smoke (pull_request) Successful in 7s
PR Checks / Build Backend (no push) (pull_request) Successful in 12s
PR Checks / Build Frontend (no push) (pull_request) Successful in 49s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 10s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 2m7s
feat(brand): use the supplied logo artwork instead of a reconstruction
The mark shipped so far was my SVG approximation, and it was wrong: the real
mark is a teardrop pin with a white window and a path flowing out of its base,
carrying three leaves — not a circle with a separate tail.

Both colourways are extracted from the supplied sheet, which has a genuinely
transparent background, so these are the artwork rather than a trace:

  public/brand/mark.png          teal pin, white window and path, green leaves
  public/brand/mark-on-dark.png  white pin with the counter knocked through

Two colourways are needed, not one. Rendered against every real ground, the
teal pin holds up on Warm White, white cards, Sand and both dark-theme grounds
— but it vanishes on the teal footer band, where only the white window
survives. The header therefore serves the teal artwork and swaps to the
on-dark artwork for dark-theme viewers through a <picture> source, needing no
JavaScript; the footer forces on-dark, because its band is teal in both
themes.

Everything downstream now derives from those two files: the favicon
(app/icon.png, replacing icon.svg), the touch icon (app/apple-icon.png,
replacing the generated apple-icon.tsx), the three PWA rasters, and the share
card, which reads public/brand/mark.png off disk so it can never drift from
the header. The logo sizing CSS keyed off a square box, which would have
squashed a 153:189 artwork — height now drives and width follows.

The wordmark stays live text in Manrope. The sheet's wordmark is a raster with
visible edge fringing, and the written style guide specifies Manrope; live
text also stays selectable, scales cleanly and recolours with the theme.

KNOWN LIMITATION: the largest instance on the sheet is 153×189. That is ample
for the header at 38px, the favicon and the share card, but short of the 512px
PWA icon, which is upscaled and slightly soft. A vector would fix it and is a
single swap — every consumer goes through components/Logo.tsx or public/brand.

Verified: tsc clean, 159/159 tests, build green, /icon.png and /apple-icon.png
emit as static routes, and the header, footer, share card and all five icons
were rendered and inspected in both themes.
2026-08-08 22:22:58 +01:00

97 lines
3.4 KiB
TypeScript

/**
* Footer Component
*
* The footer is the guideline's "brand in action" band: a deep teal anchor
* that stays teal in both themes. Everything inside it therefore reads from
* the --on-sunken-* family rather than the page's --text-* tokens, which
* invert and would go dark against the teal in one theme or the other.
*/
import { LogoMark } from './Logo';
import styles from './Footer.module.css';
export function Footer() {
const currentYear = new Date().getFullYear();
return (
<footer className={styles.footer}>
<div className={styles.container}>
<div className={styles.content}>
<div className={styles.section}>
{/*
On the sunken band the mark inverts: the pin takes the band's
foreground and the leaf is knocked out in the band itself. The
header's defaults (brand pin, card leaf) would disappear here.
*/}
<h3 className={styles.lockup}>
<span className={styles.lockupMark}>
<LogoMark variant="onDark" size={34} />
</span>
<span className={styles.wordmark}>
school<span className={styles.wordmarkAccent}>compare</span>
</span>
</h3>
<p className={styles.tagline}>Find the right school. For their future.</p>
<p className={styles.description}>
Compare primary and secondary schools across England.
</p>
<a
href="mailto:contact@schoolcompare.co.uk"
className={styles.link}
data-umami-event="contact_email_clicked"
>
contact@schoolcompare.co.uk
</a>
</div>
<div className={styles.section}>
<h4 className={styles.sectionTitle}>Product</h4>
<ul className={styles.links}>
<li><a href="/" className={styles.link}>Search schools</a></li>
<li><a href="/rankings" className={styles.link}>Rankings</a></li>
<li><a href="/compare" className={styles.link}>Compare shortlist</a></li>
<li><a href="/admissions" className={styles.link}>Admissions guide</a></li>
</ul>
</div>
<div className={styles.section}>
<h4 className={styles.sectionTitle}>Resources</h4>
<ul className={styles.links}>
<li>
<a
href="https://www.gov.uk/school-performance-tables"
target="_blank"
rel="noopener noreferrer"
className={styles.link}
data-umami-event="external_link_clicked"
data-umami-event-target="dfe"
>
School Performance Tables
</a>
</li>
<li>
<a
href="https://reports.ofsted.gov.uk/"
target="_blank"
rel="noopener noreferrer"
className={styles.link}
data-umami-event="external_link_clicked"
data-umami-event-target="ofsted"
>
Ofsted reports
</a>
</li>
</ul>
</div>
</div>
<div className={styles.bottom}>
<p className={styles.copyright}>
© {currentYear} schoolcompare.co.uk
</p>
</div>
</div>
</footer>
);
}