State
useTernaryDarkMode
Three-state dark mode — system, dark or light — persisted.
Demo
live · imported from hookli
Resolved: light
“system” follows your OS setting — the other two force a mode.
- ternaryDarkMode
- system
- isDarkMode
- false
The choice persists — reload and the panel keeps its mode.
import { useTernaryDarkMode } from "hookli";
export function Demo() {
const { isDarkMode, ternaryDarkMode, setTernaryDarkMode } =
useTernaryDarkMode();
return (
<div className={isDarkMode ? "panel-dark" : "panel-light"}>
<select
value={ternaryDarkMode}
onChange={(e) => setTernaryDarkMode(e.target.value)}
>
<option value="light">Light</option>
<option value="system">System</option>
<option value="dark">Dark</option>
</select>
</div>
);
}Usage
import { useTernaryDarkMode } from "hookli";
export function Demo() {
const { isDarkMode, ternaryDarkMode, setTernaryDarkMode } =
useTernaryDarkMode();
return (
<div className={isDarkMode ? "panel-dark" : "panel-light"}>
<select
value={ternaryDarkMode}
onChange={(e) => setTernaryDarkMode(e.target.value)}
>
<option value="light">Light</option>
<option value="system">System</option>
<option value="dark">Dark</option>
</select>
</div>
);
}API
useTernaryDarkMode(options?: UseTernaryDarkModeOptions): UseTernaryDarkModeReturnParameters
| Name | Type | Default | Description |
|---|---|---|---|
| options | UseTernaryDarkModeOptions | {} | Optional starting mode and localStorage key. |
Returns
| Name | Type | Description |
|---|---|---|
| { … } | UseTernaryDarkModeReturn | The resolved isDarkMode boolean, the stored ternary preference, and its setters. |
TernaryDarkMode
The three possible preferences.
| Name | Type | Description |
|---|---|---|
| value | "system" | "dark" | "light" | "system" resolves against the OS; "dark"/"light" force a mode. |
UseTernaryDarkModeOptions
Optional starting mode and persistence key.
| Name | Type | Description |
|---|---|---|
| defaultValue | TernaryDarkMode | The mode before anything is stored: "system", "dark" or "light". |
| localStorageKey | string | The localStorage key the choice is persisted under. |
UseTernaryDarkModeReturn
The resolved mode plus setters.
| Name | Type | Description |
|---|---|---|
| isDarkMode | boolean | True when the mode is "dark", or "system" while the OS prefers dark. |
| ternaryDarkMode | TernaryDarkMode | The stored preference: "system" | "dark" | "light". |
| setTernaryDarkMode | (value: TernaryDarkMode | ((prev: TernaryDarkMode) => TernaryDarkMode)) => void | Set the preference directly; accepts a value or an updater. |
| toggleTernaryDarkMode | () => void | Cycle the preference: light → system → dark → light. |
Hook
The implementation, straight from hookli. Copy it, or install the package.
import { useCallback } from "react";
import { useLocalStorage } from "../use-local-storage/use-local-storage";
import { useMediaQuery } from "../use-media-query/use-media-query";
type TernaryDarkMode = "system" | "dark" | "light";
interface UseTernaryDarkModeOptions {
defaultValue?: TernaryDarkMode;
localStorageKey?: string;
}
interface UseTernaryDarkModeReturn {
isDarkMode: boolean;
ternaryDarkMode: TernaryDarkMode;
setTernaryDarkMode: (
value: TernaryDarkMode | ((prev: TernaryDarkMode) => TernaryDarkMode),
) => void;
toggleTernaryDarkMode: () => void;
}
const COLOR_SCHEME_QUERY = "(prefers-color-scheme: dark)";
const DEFAULT_STORAGE_KEY = "hookli-ternary-dark-mode";
export function useTernaryDarkMode(
options: UseTernaryDarkModeOptions = {},
): UseTernaryDarkModeReturn {
const { defaultValue = "system", localStorageKey = DEFAULT_STORAGE_KEY } =
options;
const isDarkOS = useMediaQuery(COLOR_SCHEME_QUERY);
const { value: ternaryDarkMode, setStoredValue: setTernaryDarkMode } =
useLocalStorage<TernaryDarkMode>(localStorageKey, defaultValue);
const isDarkMode =
ternaryDarkMode === "dark" || (ternaryDarkMode === "system" && isDarkOS);
const toggleTernaryDarkMode = useCallback(() => {
const cycle: TernaryDarkMode[] = ["light", "system", "dark"];
setTernaryDarkMode((prev) => {
const nextIndex = (cycle.indexOf(prev) + 1) % cycle.length;
return cycle[nextIndex];
});
}, [setTernaryDarkMode]);
return {
isDarkMode,
ternaryDarkMode,
setTernaryDarkMode,
toggleTernaryDarkMode,
};
}