fix(web): make lockup logo color-scheme aware so it stays visible in dark mode - #3284
Conversation
…dark mode The shared Logo.astro component mapped variant="lockup" (used by the Header and Footer on every wheels.dev site) unconditionally to the dark-ink wheels-logo.png, which is invisible on dark backgrounds. The sites' dark mode is CSS-only (prefers-color-scheme in tokens.css), so the fix renders both the dark-ink and white lockups and toggles them with the same media query — no JS, no layout shift (hidden image is display:none). variant="mark" and variant="lockup-on-dark" are unchanged. Verified with Playwright against the built landing site: under an emulated dark color scheme the white lockup is the visible one in both header and footer; under light the dark-ink lockup renders as before. Light-mode output is pixel-identical, so the CI-captured visual baselines are untouched. Closes #3264 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Peter Amiri <petera@pai.com>
There was a problem hiding this comment.
Wheels Bot — Reviewer
TL;DR — This PR fixes the wheels.dev header/footer lockup logo being invisible in dark mode (#3264) by making variant="lockup" render both the dark-ink and white lockups and toggling them with a pure-CSS prefers-color-scheme: dark media query. The change is scoped to web/packages/ui/src/components/Logo.astro plus a changelog fragment. It is correct, well-verified, and matches the sites' CSS-only dark-mode model. Verdict: approve.
Correctness
The swap logic is sound. In light mode .wd-logo--lockup-dark { display: none } (Logo.astro:88-90) hides the white image while .wd-logo--lockup-light inherits .wd-logo { display: inline-block }; the dark-mode media query (Logo.astro:91-98) inverts this. Both selectors are single-class (specificity 0,1,0), so source order decides — and the display: none / media-query rules are authored after the base .wd-logo rule, so the intended image always wins. Astro's scoped-style data-attribute is applied uniformly, preserving that ordering. Verified the white asset exists (web/packages/ui/src/assets/wheels-logo-white.png) and that both Logo.astro consumers — Header.astro:21 and Footer.astro:11 — use variant="lockup", so both benefit. variant="mark" and variant="lockup-on-dark" are correctly left on their prior single-image paths.
Accessibility is fine: both <img> share alt="wheels.dev", but the hidden one is display:none and is ignored by assistive tech, so there is no duplicate announcement.
Docs
Changelog fragment changelog.d/3264-dark-mode-logo.fixed.md uses the correct .fixed. type (in the allowed added,changed,deprecated,removed,performance,fixed,security set) and contains a complete bullet line — the fragment-file convention, not a direct CHANGELOG.md edit. Good.
Commits
fix(web): make lockup logo color-scheme aware so it stays visible in dark mode — valid fix type, web monorepo scope, subject well under 100 chars, not ALL-CAPS. Conforms to commitlint.config.js.
Non-blocking nit (efficiency)
Logo.astro:44-59 — both lockup <img> elements are in the DOM with loading="eager", and most browsers fetch display:none images anyway, so every page load downloads both wheels-logo.png (~21KB) and wheels-logo-white.png (~8KB) even though only one renders. A <picture> with <source media="(prefers-color-scheme: dark)"> would let the browser fetch only the needed asset. Not worth blocking on for a logo pair this small, and the current approach correctly avoids layout shift — noting only for a future pass.
|
Yes. I can see it again on Chrome (windows desktop) again! |
Closes #3264
Problem
The Wheels logo is invisible on wheels.dev in dark mode (reported from iOS Safari).
Logo.astromappedvariant="lockup"unconditionally to the dark-inkwheels-logo.png, and bothHeader.astroandFooter.astrouse that variant — so every site consuming the shared header/footer (landing, guides, api, blog, packages) showed a dark logo on a dark background.Fix
web/packages/ui/src/components/Logo.astroonly. The sites' dark mode is CSS-only (@media (prefers-color-scheme: dark)intokens.css— no JS toggle, nodata-theme), so the swap is pure CSS too:variant="lockup"now renders both the dark-ink and the white lockup (wheels-logo-white.png, already an asset of this component) and toggles them with the sameprefers-color-scheme: darkmedia query. The hidden image isdisplay:none, so there's no layout shift.variant="mark"andvariant="lockup-on-dark"are unchanged.changelog.d/3264-dark-mode-logo.fixed.mdfragment.This is the fix shape wheels-bot proposed on the issue (it couldn't open the PR itself because
web/is outside the TDD-gated scope — hence thedocs/bot-*branch prefix).Verification
No CFML spec surface (pure static-site change), so verification is against the built sites:
pnpm build), and every dist's pages contain the light/dark lockup pair + scoped media-query CSS.pnpm test; only the packages site has test files).colorScheme: darkthe white lockup is the computed-visible image in both header and footer (page bgrgb(15,15,14)); underlightthe dark-ink lockup renders exactly as before.pnpm formatrun on the changed file;prettier --checkpasses for it (40 other files have pre-existing style drift ondevelop— left untouched).Visual baselines
Deliberately not refreshed: light-mode rendering is pixel-identical (the local visual run diffs the base commit and this branch against the CI-captured Linux baselines by the exact same pixel count — 77,873 px on landing — i.e. the entire diff is the documented macOS-vs-CI font-rendering mismatch, zero pixels attributable to this change). The baselines are light-mode CI captures, and the script itself warns local refreshes poison them — if a dark-mode baseline is ever added it should come from the CI artifact.
🤖 Generated with Claude Code