If no value exists in local storage, it will default to "system", though this can be changed by using the defaultValue hook parameter.
Note: If you use this hook in an SSR context, set the initializeWithValue option to false.
Returned value
-
The
isDarkModeis a boolean for the final outcome, to let you be able to use with your logic. -
The
ternaryModeCodeis of a literal type"dark" | "system" | "light".When
ternaryModeCodeis set tosystem, theisDarkModewill use system theme, like of iOS and MacOS.Also,
ternaryModeCodeimplicitly exports a type withtype TernaryDarkMode = typeof ternaryDarkMode
Returned interface
- The
toggleTernaryDarkModeis a function to cycleternaryModeCodebetweendark,systemandlight(in this order). - The
setTernaryDarkModeaccepts a parameter of typeTernaryDarkModeand set it asternaryModeCode.
Usage
import { useTernaryDarkMode } from './useTernaryDarkMode'
type TernaryDarkMode = ReturnType<typeof useTernaryDarkMode>['ternaryDarkMode']
export default function Component() {
const { isDarkMode, ternaryDarkMode, setTernaryDarkMode, toggleTernaryDarkMode } =
useTernaryDarkMode()
return (
<div>
<p>Current theme: {isDarkMode ? 'dark' : 'light'}</p>
<p>ternaryMode: {ternaryDarkMode}</p>
<p>
Toggle between three modes
<button onClick={toggleTernaryDarkMode}>Toggle from {ternaryDarkMode}</button>
</p>
<p>
Select a mode
<br />
<select
name="select-ternaryDarkMode"
onChange={ev => {
setTernaryDarkMode(ev.target.value as TernaryDarkMode)
}}
value={ternaryDarkMode}
>
<option value="light">light</option>
<option value="system">system</option>
<option value="dark">dark</option>
</select>
</p>
</div>
)
}
API
function useTernaryDarkMode(options?: TernaryDarkModeOptions): TernaryDarkModeReturn
Custom hook that manages ternary (system, dark, light) dark mode with local storage support.
Parameters
| Name | Type | Default value | Description |
|---|---|---|---|
options? | TernaryDarkModeOptions | {} | Options or the local storage key for the hook. |
Returns
An object containing the dark mode state and helper functions.
Type declaration
TernaryDarkMode
Ternary dark mode options.
TernaryDarkModeOptions
Options for the useTernaryDarkMode hook.
| Name | Type | Description |
|---|---|---|
defaultValue | TernaryDarkMode | The default value for the dark mode. |
initializeWithValue | boolean | If true (default), the hook will initialize reading localStorage. In SSR, you should set it to false, returning default values initially. |
localStorageKey | string | The key for storing dark mode preference in local storage. |
TernaryDarkModeReturn
Represents the return type of the useTernaryDarkMode hook.
| Name | Type | Description |
|---|---|---|
isDarkMode | boolean | The current state of the dark mode. |
setTernaryDarkMode | Dispatch<SetStateAction<TernaryDarkMode>> | A function to set the dark mode state. |
ternaryDarkMode | TernaryDarkMode | The current state of the dark mode. |
toggleTernaryDarkMode | () => void | A function to toggle the dark mode state. |
Hook
import type { Dispatch, SetStateAction } from 'react'
import { useLocalStorage } from '../useLocalStorage'
import { useMediaQuery } from '../useMediaQuery'
const COLOR_SCHEME_QUERY = '(prefers-color-scheme: dark)'
const LOCAL_STORAGE_KEY = 'usehooks-ts-ternary-dark-mode'
/** Ternary dark mode options. */
export type TernaryDarkMode = 'system' | 'dark' | 'light'
/** Options for the `useTernaryDarkMode` hook. */
export type TernaryDarkModeOptions = {
/**
* The default value for the dark mode.
* @default 'system'
*/
defaultValue?: TernaryDarkMode
/**
* The key for storing dark mode preference in local storage.
* @default 'usehooks-ts-ternary-dark-mode'
*/
localStorageKey?: string
/**
* If `true` (default), the hook will initialize reading `localStorage`. In SSR, you should set it to `false`, returning default values initially.
* @default true
*/
initializeWithValue?: boolean
}
/** Represents the return type of the `useTernaryDarkMode` hook. */
export type TernaryDarkModeReturn = {
/** The current state of the dark mode. */
isDarkMode: boolean
/** The current state of the dark mode. */
ternaryDarkMode: TernaryDarkMode
/** A function to set the dark mode state. */
setTernaryDarkMode: Dispatch<SetStateAction<TernaryDarkMode>>
/** A function to toggle the dark mode state. */
toggleTernaryDarkMode: () => void
}
/**
* Custom hook that manages ternary (system, dark, light) dark mode with local storage support.
* @param {?TernaryDarkModeOptions | string} [options] - Options or the local storage key for the hook.
* @returns {TernaryDarkModeReturn} An object containing the dark mode state and helper functions.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-ternary-dark-mode)
* @example
* ```tsx
* const { isDarkMode, ternaryDarkMode, setTernaryDarkMode, toggleTernaryDarkMode } = useTernaryDarkMode({ defaultValue: 'dark' });
* // Access and use the dark mode state and provided helper functions.
* ```
*/
export function useTernaryDarkMode({
defaultValue = 'system',
localStorageKey = LOCAL_STORAGE_KEY,
initializeWithValue = true,
}: TernaryDarkModeOptions = {}): TernaryDarkModeReturn {
const isDarkOS = useMediaQuery(COLOR_SCHEME_QUERY, { initializeWithValue })
const [mode, setMode] = useLocalStorage(localStorageKey, defaultValue, {
initializeWithValue,
})
const isDarkMode = mode === 'dark' || (mode === 'system' && isDarkOS)
const toggleTernaryDarkMode = () => {
const modes: TernaryDarkMode[] = ['light', 'system', 'dark']
setMode((prevMode) => {
const prevIndex = modes.indexOf(prevMode)
const nextIndex = (prevIndex + 1) % modes.length
return modes[nextIndex] as TernaryDarkMode
})
}
return {
isDarkMode,
ternaryDarkMode: mode,
setTernaryDarkMode: setMode,
toggleTernaryDarkMode,
}
}