# Theme Implementation Guide: Dark and Light Themes ## Overview This guide outlines critical implementation patterns for dark and light themes using next-themes in Next.js applications, based on best practices and real-world implementation experience. This is a strict requirement for this website throughout. ## Core Architecture Principles ### 1. CSS Variable Strategy (Primary Approach) **ALWAYS USE**: CSS variables with semantic naming for theme switching **AVOID**: Inline `dark:` classes throughout components ```css :root { /* Semantic color variables - light theme defaults */ --color-text: #1e293b; --color-text-light: #64748b; --color-bg: #ffffff; --color-bg-secondary: #f8fafc; --color-primary: #1a56db; --color-border: #e2e8f0; } .dark { /* Dark theme overrides */ --color-text: #f3f4f6; --color-text-light: #e5e7eb; --color-bg: #0f172a; --color-bg-secondary: #1e293b; --color-primary: #60a5fa; --color-border: #475569; } ``` ### 2. Component Class Pattern Create semantic CSS classes that reference variables: ```css .card { background-color: var(--color-bg-secondary); color: var(--color-text); border: 1px solid var(--color-border); } .card-title { color: var(--color-text); } .card-description { color: var(--color-text-light); } ``` **Component Usage**: ```jsx // ✅ CORRECT - Uses semantic classes

Title

Description

// ❌ AVOID - Inline dark: classes

Title

Description

``` ## next-themes Implementation Checklist ### 1. Essential Setup ```jsx // app/layout.tsx import { ThemeProvider } from 'next-themes' export default function Layout({ children }) { return ( {children} ) } ``` ### 2. Theme Toggle Component ```jsx 'use client' import { useTheme } from 'next-themes' import { useEffect, useState } from 'react' export function ThemeToggle() { const [mounted, setMounted] = useState(false) const { theme, setTheme } = useTheme() // Prevent hydration mismatch useEffect(() => setMounted(true), []) if (!mounted) return null // Critical for SSR return ( ) } ``` ## Critical Implementation Rules ### 1. NEVER Access Theme During SSR ```jsx // ❌ WRONG - Causes hydration mismatch function Component() { const { theme } = useTheme() return (
Content
) } // ✅ CORRECT - Use CSS variables only function Component() { return (
Content
) } ``` ### 2. Always Check Mount State ```jsx // ✅ CORRECT Pattern function ThemeAwareComponent() { const [mounted, setMounted] = useState(false) const { theme } = useTheme() useEffect(() => setMounted(true), []) if (!mounted) { return
// Fallback UI } // Safe to use theme here return
Theme: {theme}
} ``` ### 3. CSS Variable Hierarchy Structure variables from general to specific: ```css :root { /* 1. Brand Colors (theme-independent) */ --brand-primary: #1a56db; --brand-secondary: #7e3af2; /* 2. Semantic Colors (theme-dependent) */ --color-text: #1e293b; --color-text-light: #64748b; --color-text-muted: #94a3b8; /* 3. Component Colors (derived from semantic) */ --card-bg: var(--color-bg-secondary); --card-text: var(--color-text); --card-border: var(--color-border); /* 4. State Colors */ --color-success: #059669; --color-warning: #d97706; --color-error: #dc2626; } ``` ## Accessibility Requirements ### 1. Contrast Ratios Ensure WCAG AA compliance (4.5:1 for normal text, 3:1 for large text): ```css :root { --color-text: #1e293b; /* 16.8:1 ratio on white */ --color-text-light: #64748b; /* 7.2:1 ratio on white */ } .dark { --color-text: #f3f4f6; /* 17.4:1 ratio on dark bg */ --color-text-light: #e5e7eb; /* 13.8:1 ratio on dark bg */ } ``` ### 2. Focus Management ```css *:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--color-primary); } .dark *:focus-visible { box-shadow: 0 0 0 3px var(--color-primary-light); } ``` ### 3. Reduced Motion Support ```css @media (prefers-reduced-motion: reduce) { .card { transition: none; } } ``` ## Common Pitfalls & Solutions ### 1. Flash of Unstyled Content (FOUC) **Problem**: Theme flashes on page load **Solution**: Use `suppressHydrationWarning` and CSS-only theme switching ### 2. Hydration Mismatches **Problem**: Server renders light theme, client uses dark theme **Solution**: Never conditionally render based on theme in components ### 3. CSS Specificity Issues **Problem**: `dark:` classes not applying **Solution**: Use CSS variables and `.dark` attribute selectors ### 4. Performance Issues **Problem**: Re-rendering on theme change **Solution**: CSS-only theme switching, avoid theme-dependent useEffect ## Testing Checklist ### 1. Theme Switching - [ ] Light to dark transition works smoothly - [ ] Dark to light transition works smoothly - [ ] System preference detection works - [ ] Theme persists across page refreshes - [ ] Theme syncs across browser tabs ### 2. SSR & Hydration - [ ] No hydration warnings in console - [ ] No FOUC on page load - [ ] Server-rendered HTML matches client - [ ] Theme toggle works immediately after mount ### 3. Accessibility - [ ] All text meets contrast requirements - [ ] Focus indicators visible in both themes - [ ] Screen reader compatibility maintained - [ ] Keyboard navigation works in both themes ## Debugging Guide ### 1. Hydration Issues ```bash # Check for hydration warnings npm run dev # Look for: "Warning: Text content did not match" ``` ### 2. CSS Variable Debugging ```css /* Add to debug CSS variables */ .debug-vars::before { content: "text: " var(--color-text) " | bg: " var(--color-bg); position: fixed; top: 0; left: 0; background: red; color: white; z-index: 9999; } ``` ### 3. Theme State Debugging ```jsx // Add to components for debugging const { theme, resolvedTheme, systemTheme } = useTheme() console.log({ theme, resolvedTheme, systemTheme }) ``` ## Performance Best Practices ### 1. CSS Variable Optimization - Use HSL values for easier manipulation - Group related variables together - Minimize number of custom properties - Use inheritance where possible ### 2. Component Optimization - Avoid theme-dependent useEffect hooks - Use CSS-only animations and transitions - Minimize JavaScript theme logic - Prefer CSS variables over conditional classes ## Migration Strategy ### From Inline Classes to CSS Variables 1. **Audit**: Find all `dark:` classes in codebase 2. **Extract**: Create semantic CSS variables 3. **Replace**: Convert components to use CSS classes 4. **Test**: Verify theme switching works 5. **Cleanup**: Remove unused dark: classes ### Example Migration ```jsx // Before

Title

Description

// After

Title

Description

``` ```css .content-container { background-color: var(--color-bg); color: var(--color-text); } .content-title { color: var(--color-text); } .content-description { color: var(--color-text-light); } ``` ## Gold Accent System (Dark Theme Exclusive) ### Current Implementation The website features a bright daisy yellow gold accent system that enhances the dark theme experience while remaining invisible in light theme. ### Color Variable ```css :root { /* Bright Daisy Yellow Accent */ --color-accent-gold: #FFD700; } ``` ### Gold Accent Components #### 1. Hero Section Gold Button Border ```css .hero-button-gold-accent { border: 2px solid transparent; transition: all 0.3s ease; } .dark .hero-button-gold-accent { border-color: var(--color-accent-gold); } .dark .hero-button-gold-accent:hover { box-shadow: 0 0 0 1px var(--color-accent-gold); } ``` #### 2. Event & Benefit Cards Gold Accents ```css .event-card-gold-border { border-left: 3px solid transparent; transition: all 0.3s ease; } .dark .event-card-gold-border:hover { border-left-color: var(--color-accent-gold); } .event-card-title-gold { transition: color 0.3s ease; } .dark .event-card-gold-border:hover .event-card-title-gold { color: var(--color-accent-gold); } ``` #### 3. Video Container Gold Frame ```css .video-container-gold { border: 2px solid transparent; transition: all 0.3s ease; } .dark .video-container-gold { border-color: var(--color-accent-gold); } ``` ### Implementation Pattern **Key Principle**: Gold accents are **dark theme exclusive** - Light theme: `transparent` borders and no color changes - Dark theme: Bright daisy yellow (`#FFD700`) accents **Component Usage**: ```jsx // Hero secondary button // Event/Benefit cards

Card Title

// Video container
{/* Video content */}
``` ### Current Gold Accents Applied 1. **Hero "Join OCD" Button**: Gold border accent 2. **Featured Event Cards**: Left border + title color on hover 3. **Membership Benefit Cards**: Left border + title color on hover 4. **Video Container**: Gold border frame ### Design Philosophy - **Subtle Enhancement**: Gold adds elegance without overwhelming - **Interactive Feedback**: Hover states provide clear user interaction cues - **Theme Consistency**: Maintains clean light theme, enhances dark theme - **Accessibility**: Bright daisy yellow provides excellent contrast on dark backgrounds ## Conclusion Always prioritize CSS variables over inline dark: classes, ensure proper SSR handling, maintain accessibility standards, and test thoroughly across all theme combinations. The gold accent system demonstrates proper CSS variable methodology while providing enhanced visual appeal exclusively in dark theme. This approach provides better performance, maintainability, and user experience.