React useTernaryDarkMode Hook
React useTernaryDarkMode hook for ternary dark mode management. Handle system, dark, and light modes with automatic system preference detection using TypeScript for Next.js.
Building advanced theme systems?
Join our Discord community for help from other developers.
Ever tried to implement a proper dark mode toggle in React and ended up with boolean state chaos, broken system preference detection, or missing auto mode functionality? You know the drill—manually managing light/dark state, forgetting to handle system preferences, dealing with localStorage persistence complexity, handling SSR hydration mismatches. This free open source React useTernaryDarkMode custom hook handles all that theme management complexity so you can focus on building beautiful interfaces instead of debugging mode switching edge cases in your React applications.
useTernaryDarkMode showcase
Smart ternary dark mode with system preference integration and persistent storage:
This free open source React hook simplifies theme management with TypeScript support for modern JavaScript applications. Whether you're building responsive dashboards, user preference systems, or accessibility-focused interfaces in your Next.js projects, this React hook keeps your dark mode implementation reliable and user-friendly.
Installation
npx shadcn@latest add https://www.shadcn.io/registry/use-ternary-dark-mode.json
npx shadcn@latest add https://www.shadcn.io/registry/use-ternary-dark-mode.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/use-ternary-dark-mode.json
bunx shadcn@latest add https://www.shadcn.io/registry/use-ternary-dark-mode.json
Why most ternary dark mode implementations suck
Look, you could keep managing theme state with useState and media queries. But then you hit the dark mode complexity—missing system preference integration, broken persistence across sessions, inconsistent state synchronization, SSR hydration issues with theme flashing in React applications.
Most developers manually manage light/dark state with boolean flags, missing the crucial "system" option that modern users expect in TypeScript components. Or they handle system preferences with manual media query listeners that break when unmounting components, causing memory leaks and stale event handlers. Some skip localStorage persistence entirely and lose user preferences on page refresh in Next.js projects.
This React hook uses optimized theme management under the hood, with automatic system preference detection and seamless localStorage integration in JavaScript applications. The browser handles all the preference events, plus you get comprehensive state management and type safety in one call.
Plus it handles all the edge cases—SSR compatibility with controlled hydration, automatic system preference synchronization, persistent storage with fallbacks, proper cleanup and memory management in React development. No more theme flashing or broken dark mode implementations.
This free open source React hook manages theme state while you focus on building features. Whether you're creating React applications, Next.js dashboards, or TypeScript components, reliable theme management keeps your JavaScript development smooth.
Features
- Ternary mode support with light, dark, and system preference detection in React applications
- System preference tracking automatically following OS dark mode settings in TypeScript components
- Persistent storage remembering user choice across browser sessions in Next.js projects
- Type-safe implementation with comprehensive TypeScript definitions and enums for JavaScript development
- SSR compatibility with proper server-side rendering support and initialization options for React frameworks
- Performance optimized using memoized callbacks and efficient event listeners in modern applications
- Free open source designed for modern React development workflows
When you'll actually use this
Real talk—this isn't for simple light/dark toggles in React applications. Basic boolean state handles binary theme switching perfectly. But when you need proper system preference integration with user override capabilities, this React hook delivers in Next.js projects.
Perfect for:
- Application themes - Provide light, dark, and auto modes for user preference built with TypeScript
- Dashboard interfaces - Let users choose themes while respecting system settings using React patterns
- Accessibility compliance - Support system-level dark mode preferences automatically in JavaScript applications
- User preference systems - Remember theme choices across browser sessions in React components
- Multi-tenant applications - Consistent theme management across different environments in Next.js applications
- Developer tools - Provide theme options that match user's development environment using TypeScript safety
API Reference
useTernaryDarkMode
useTernaryDarkMode(
options?: TernaryDarkModeOptions
): UseTernaryDarkModeReturn
Parameter | Type | Default | Description |
---|---|---|---|
options | TernaryDarkModeOptions | {} | Configuration options for theme management |
TernaryDarkModeOptions
Property | Type | Default | Description |
---|---|---|---|
defaultValue | TernaryDarkMode | "system" | Initial theme mode value |
localStorageKey | string | "use-ternary-dark-mode" | Key for localStorage persistence |
initializeWithValue | boolean | true | Whether to initialize with stored value (set to false for SSR) |
UseTernaryDarkModeReturn
Property | Type | Description |
---|---|---|
isDarkMode | boolean | Current computed dark mode state based on ternary mode and system preference |
ternaryDarkMode | TernaryDarkMode | Current ternary mode value ('system', 'dark', or 'light') |
setTernaryDarkMode | Dispatch<SetStateAction<TernaryDarkMode>> | Function to set the ternary mode directly |
toggleTernaryDarkMode | () => void | Function to cycle through the three modes sequentially |
TernaryDarkMode
type TernaryDarkMode = "system" | "dark" | "light";
Common gotchas
System preference changes update automatically: When set to "system" mode, the React hook listens for OS-level dark mode changes and updates isDarkMode
automatically in React applications. This behavior is intentional but means your UI will respond to system changes in real-time.
localStorage persistence is automatic: The React hook saves the user's theme choice (light/dark/system) but not the computed isDarkMode
value in TypeScript components. When "system" is selected, the actual dark mode state is always computed fresh from current system preferences.
SSR requires careful initialization: Use initializeWithValue: false
to prevent hydration mismatches in Next.js projects. The hook will return default values initially and update with stored preferences after client hydration.
Toggle cycles through all three modes: The toggleTernaryDarkMode
function cycles: light → system → dark → light in JavaScript applications. For custom toggle behavior, use setTernaryDarkMode
directly with your own logic.
System mode follows OS changes: When users have "system" selected, the theme will automatically switch if they change their OS theme settings in React frameworks. This can be unexpected if users don't understand the "system" option.
Media query listener cleanup: The React hook automatically manages media query listeners in TypeScript projects. Manual cleanup is handled when components unmount, preventing memory leaks.
Related hooks you will also like
useDarkMode
Simple binary dark mode toggle without system preference support
useMediaQuery
Media query detection for system dark mode preference tracking
useLocalStorage
Persistent storage for theme preferences across sessions
useToggle
Toggle state management for theme switching interfaces
useIsClient
Client detection needed for safe theme initialization
useEventListener
Event handling for system preference change detection
Questions you might have
React useStep Hook
React useStep hook for step navigation. Manage multi-step processes with automatic boundary checking and progress tracking using TypeScript for Next.js apps.
React useTimeout Hook
React useTimeout hook for setTimeout management. Handle delayed actions with automatic cleanup, dynamic control, and cancellation support using TypeScript for Next.js.