Overview
The theme system is built with React Context and supports three modes:- Light mode: Bright, clean appearance optimized for daytime use
- Dark mode: Low-light friendly with reduced eye strain
- System mode: Automatically follows the user’s operating system preferences
Implementation
The theme system is implemented inThemeContext.tsx using React Context API and provides automatic theme persistence via localStorage.
ThemeProvider
Wrap your application with theThemeProvider to enable theming throughout your app:
Using the Theme Hook
Access theme functionality anywhere in your app using theuseTheme hook:
Theme API
TheuseTheme hook returns the following properties and methods:
| Property | Type | Description |
|---|---|---|
theme | 'light' | 'dark' | 'system' | The currently selected theme mode |
resolvedTheme | 'light' | 'dark' | The actual theme being displayed (resolves ‘system’ to ‘light’ or ‘dark’) |
setTheme | (theme: Theme) => void | Manually set the theme mode |
toggleTheme | () => void | Toggle between light and dark modes |
mounted | boolean | Indicates if the theme has been initialized (prevents flash of wrong theme) |
How It Works
Initialization
On mount, the theme provider checks localStorage for a saved theme preference. If none exists, it defaults to ‘system’ mode.
Theme Resolution
For ‘system’ mode, the provider listens to the
prefers-color-scheme media query to detect the OS preference. For explicit ‘light’ or ‘dark’ modes, it applies them directly.DOM Application
The resolved theme is applied by adding or removing the ‘dark’ class on the document root element (
<html>).Design Tokens
The theme system uses CSS custom properties (variables) for consistent styling across components. All tokens are defined inglobals.css and automatically update based on the active theme.
Color Tokens
Primary Colors
Semantic Colors
| Token | Light Mode | Dark Mode | Usage |
|---|---|---|---|
--accent | #14b8a6 (Teal) | #2dd4bf | Highlights and CTAs |
--success | #10b981 (Emerald) | #34d399 | Success states |
--warning | #f59e0b (Amber) | #fbbf24 | Warnings |
--destructive | #f43f5e (Rose) | #fb7185 | Errors and destructive actions |
Surface Colors
Spacing & Layout
Border Radius
Shadows
Shadow opacity is increased in dark mode (0.3-0.4) for better depth perception against dark backgrounds.
Transitions
Using Design Tokens
Access design tokens in your CSS or components:In CSS
In Tailwind CSS
Design tokens are mapped to Tailwind classes:Advanced Features
System Theme Sync
When set to ‘system’ mode, the theme automatically updates when the user changes their OS preferences:Preventing Theme Flash
Use themounted property to prevent flash of unstyled content:
Example: Theme Switcher
Create a complete theme switcher component:Best Practices
Always use design tokens instead of hardcoded colors to ensure your components automatically adapt to theme changes.
- Use semantic color tokens (
--primary,--success, etc.) instead of specific colors - Test components in both themes to ensure readability and accessibility
- Leverage the
mountedflag to prevent flash of unstyled content - Provide theme toggle UI in an accessible location (header, settings, etc.)
- Use CSS transitions for smooth theme switching animations
Source Code References
- Theme Context:
client/app/context/ThemeContext.tsx - Design Tokens:
client/app/globals.css:4-122 - Theme Hook:
client/app/context/ThemeContext.tsx:84-87