Dark mode has become a standard expectation in modern web applications. But implementing it correctly—with persistence, system preference detection, and clean separation of logic and styles—is often more complicated than it should be.
That’s exactly why I built use-theme-mode, a lightweight React hook that handles theme state for you—without enforcing any styling system.
✨ Why Another Theme Hook?
Most theme solutions today fall into one of two categories:
- Too opinionated (UI framework–specific)
- Too heavy for simple use cases
I wanted something that:
- ✅ Works with any CSS solution
- ✅ Persists user preference
- ✅ Respects system theme
- ✅ Is SSR‑safe
- ✅ Has zero runtime dependencies
That became use-theme-mode.
📦 Installation
npm install use-theme-mode
🚀 Basic Usage
import { useTheme } from "use-theme-mode";
function App() {
const { theme, toggleTheme } = useTheme();
return (
<button onClick={toggleTheme}>
Current theme: {theme}
</button>
);
}
That’s it. Behind the scenes, the hook:
- Detects system preference
- Saves the theme to
localStorage - Updates the
<html data-theme="...">attribute - Syncs changes across tabs
🎨 Styling Is 100% in Your Control
use-theme-mode does not inject styles. Instead, it gives you a single source of truth via data-theme.
CSS Implementation
:root[data-theme="light"] {
--bg-color: #ffffff;
--text-color: #000000;
}
:root[data-theme="dark"] {
--bg-color: #121212;
--text-color: #ffffff;
}
body {
background-color: var(--bg-color);
color: var(--text-color);
transition: background 0.3s ease, color 0.3s ease;
}
This approach works beautifully with:
- Tailwind
- CSS variables
- Styled-components
- MUI / Chakra
- Vanilla CSS
🔄 Works Great with Tailwind Too
JavaScript Configuration:
// tailwind.config.js
module.exports = {
darkMode: ["attribute", "data-theme"],
};
JSX Usage:
<div className="bg-white text-black dark:bg-black dark:text-white">
Hello world
</div>
🌍 Live Demo
I’ve deployed a live demo showcasing:
- Real theme switching
- Persistent state
- Code examples synced with UI
🧩 API Reference
const { theme, toggleTheme, setLight, setDark } = useTheme();
-
theme→"light" | "dark" -
toggleTheme()→ switch modes -
setLight()→ force light mode -
setDark()→ force dark mode
🛡️ SSR Safe & Production Ready
The hook:
- Avoids direct
windowaccess during render. - Works in Next.js and other SSR frameworks.
- Synchronizes changes across tabs automatically.
🔮 What’s Coming Next?
Plans for future versions:
- ✅ TypeScript-first API
- ✅ Optional context provider
- ✅ ESM build support
- ✅ Custom storage keys
🔗 Links
- npm: use-theme-mode
- GitHub: saadahmad888/use-theme-mode
- Live Demo: Vercel Demo
If you find this useful, I’d love feedback or contributions!
Top comments (0)