Theme Provider
Problem
Each component fetches and manages its own theme values, leading to duplicated theme logic and inconsistent colors when some components miss theme updates. Implementing dark mode or allowing users to switch themes requires modifying every component individually, and there’s no single source of truth for the current theme state.
Solution
Supply theme values through context so child components can access design tokens consistently. This centralizes theming and makes it easy to switch themes dynamically.
Example
This demonstrates centralizing theme management to provide consistent design tokens across all components and enable runtime theme switching like dark mode.
// Framework-agnostic theme management with CSS custom properties
class ThemeProvider {
constructor() {
this.theme = 'light'; // Current theme
this.listeners = []; // Components listening for changes
}
setTheme(newTheme) {
this.theme = newTheme;
// Update data attribute - CSS can react to this
document.documentElement.setAttribute('data-theme', newTheme);
// Notify all subscribed components
this.listeners.forEach(listener => listener(newTheme));
}
subscribe(listener) {
this.listeners.push(listener);
// Return unsubscribe function
return () => {
const index = this.listeners.indexOf(listener);
this.listeners.splice(index, 1);
};
}
}
// Usage
const themeProvider = new ThemeProvider();
// Components can listen for theme changes
themeProvider.subscribe(theme => {
console.log('Theme changed to:', theme);
});
// Switch themes at runtime
themeProvider.setTheme('dark');
Benefits
- Centralizes theme management with single source of truth.
- Makes adding features like dark mode straightforward.
- Ensures consistent theming across all components.
- Enables runtime theme switching without page reloads.
Tradeoffs
- Can cause re-renders when theme changes affect entire component tree.
- May need optimization to prevent unnecessary re-renders.
- Requires components to consume theme context instead of hardcoding values.
- Adds complexity compared to simple CSS custom properties.