Skip to content

dark mode#249

Open
codefather2026 wants to merge 1 commit into
MettaChain:mainfrom
codefather2026:main
Open

dark mode#249
codefather2026 wants to merge 1 commit into
MettaChain:mainfrom
codefather2026:main

Conversation

@codefather2026
Copy link
Copy Markdown

Fix #243: Replace Manual Theme Mutation with next-themes Provider System
Summary
This PR addresses the issue where the application was managing dark mode through direct documentElement mutation, with no persistence or hydration safety — resulting in theme flicker on navigation, inconsistent state across routes, and a poor developer experience.
Problem Statement
The previous implementation was:

Mutating document.documentElement directly for theme changes
Providing no theme persistence across sessions
Causing hydration mismatches and flash-of-incorrect-theme (FOIT)
Scattering theme logic without a single source of truth
Breaking dark backgrounds on referral pages
Lacking a globally accessible theme toggle

Solution Implemented
✨ New Dark Mode Architecture

  1. Theme Provider (src/utils/ThemeProvider.tsx, line 1)

next-themes integration at the app root for global coverage
localStorage persistence so user preference survives page reloads
Instant propagation across all routes without manual re-wiring
System preference support as the default fallback

  1. Updated Application Root (src/app/layout.tsx, line 37)

Provider mounted at root so all child routes inherit theme context
No per-route theme wiring needed going forward

  1. Client Providers Integration (src/components/ClientProviders.tsx, line 64)

ThemeProvider composed within the client provider tree
Correct SSR boundary placement to prevent hydration errors

  1. Global Theme Toggle (src/components/GlobalThemeToggle.tsx, line 1)

Floating app-wide control accessible from any route
Provider-backed state replaces direct DOM mutation
Single source of truth for reading and setting the active theme

  1. Hydration-Safe Theme Switcher (src/components/ThemeSwitcher.tsx, line 1)

Refactored to use provider state instead of documentElement manipulation
Accessible markup with proper ARIA attributes
Suppressed hydration mismatch using mounted guard pattern

  1. Referral Page Dark Mode Fixes

src/app/referral/page.tsx (line 13) — updated to honor dark background tokens
src/app/referral/leaderboard/page.tsx (line 13) — same dark mode background fix applied

  1. Global Color-Scheme Handling (src/app/globals.css, line 104)

color-scheme CSS property set per theme to ensure native UI elements (scrollbars, inputs) respect the active mode
Smooth transitions between light and dark without layout shift

🎯 Acceptance Criteria Met
✅ Theme changes apply at the app root

ThemeProvider wraps the full component tree via layout.tsx
No route requires individual theme setup

✅ Theme persists in localStorage

next-themes handles read/write automatically
Preference survives hard refreshes and new sessions

✅ Theme updates instantly across routes

Provider context propagates changes reactively
No full-page reload or manual DOM sync needed

✅ Manual documentElement mutation removed

ThemeSwitcher.tsx and GlobalThemeToggle.tsx both use provider state exclusively
No direct DOM theme manipulation anywhere in the codebase

✅ Hydration safety implemented

ThemeSwitcher.tsx uses a mounted guard to prevent SSR/client mismatch
No flash-of-incorrect-theme on initial load

✅ Referral pages respect dark mode

Both referral routes updated with correct dark background classes
Consistent with the rest of the app's theme tokens

📝 Migration Guide
For Existing Components

Replace document.documentElement.classList.toggle('dark') → const { setTheme } = useTheme()
Replace manual localStorage.setItem('theme', ...) → handled automatically by next-themes
Add mounted guard before rendering theme-dependent UI to avoid hydration errors

For New Development

Use useTheme() hook from next-themes to read or set the theme
Wrap any SSR-sensitive theme UI in a mounted check
Use CSS color-scheme for native element theming in new stylesheets

🔮 Future Enhancements

Per-user theme preference synced server-side
Additional theme variants beyond light/dark (e.g. high-contrast)
Animated theme transition effects

📋 Files Changed

Created: src/utils/ThemeProvider.tsx
Modified: src/app/layout.tsx
Modified: src/components/ClientProviders.tsx
Created: src/components/GlobalThemeToggle.tsx
Modified: src/components/ThemeSwitcher.tsx
Modified: src/app/referral/page.tsx
Modified: src/app/referral/leaderboard/page.tsx
Modified: src/app/globals.css

✅ Verification

next-themes provider wired at app root
Theme persists in localStorage across sessions
Instant theme propagation across all routes
All manual documentElement mutation removed
Hydration-safe ThemeSwitcher implemented
GlobalThemeToggle accessible app-wide
Referral pages honor dark mode backgrounds
color-scheme property set in global CSS

@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented May 26, 2026

@codefather2026 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Frontend Issue: Implement Dark Mode Support

2 participants