Skip to content

Eliminate the dark-mode flash by applying the theme before first paint #20

@mikewheeleer

Description

@mikewheeleer

Improve theming to prevent the flash of incorrect color scheme (FOUC)

Description

Theme is applied entirely client-side: src/components/ThemeToggle.tsx toggles the dark class on documentElement inside a useEffect, so a user who chose dark mode sees a white flash on every navigation until hydration runs. src/app/layout.tsx hard-codes <html lang="en"> with no early theme application and the CSS in src/app/globals.css relies solely on prefers-color-scheme. This issue applies the stored theme before first paint.

Requirements and context

  • Repository scope: Agentpay-Org/Agentpay-frontend only.
  • Inject a tiny blocking inline script in src/app/layout.tsx <head> that reads agentpay.theme from localStorage (key matches src/lib/theme.ts) and sets the dark class synchronously before the body renders.
  • Ensure the system setting still honours prefers-color-scheme and that the script is the single source of truth shared with src/lib/theme.ts (no key drift).
  • Respect prefers-reduced-motion where any theme-transition CSS is added.

Suggested execution

  • Fork the repo and create a branch
  • git checkout -b a11y/a11y-21-theme-fouc
  • Implement changes
    • Write code in: src/app/layout.tsx (inline pre-paint script) and reconcile src/lib/theme.ts.
    • Write comprehensive tests in: create src/lib/__tests__/theme.test.ts cases or a layout test asserting the storage key and class logic match.
    • Add documentation: document the anti-FOUC approach in README.md.
    • Validate no hydration mismatch warning is produced.
  • Test and commit

Test and commit

  • Run npm run lint, npm run typecheck, npm test, and npm run build.
  • Cover edge cases: no stored theme (defaults to system), corrupt stored value, and SSR with localStorage absent.
  • Include the npm test output and a note confirming no hydration warnings in npm run dev.

Example commit message

fix(a11y): apply stored theme before first paint to remove dark-mode flash

Guidelines

  • Minimum 95 percent test coverage for the touched theme logic.
  • Clear, reviewer-focused documentation.
  • Timeframe: 96 hours.

Community & contribution rewards

  • 💬 Join the AgentPay community on Discord for questions, reviews, and faster merges: https://discord.gg/eXvRKkgcv
  • ⭐ This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project — if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward.

Metadata

Metadata

Assignees

No one assigned
    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions