Skip to main content

All hooks

useTernaryDarkMode

Custom hook that manages ternary (system, dark, light) dark mode with local storage support.


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 isDarkMode is a boolean for the final outcome, to let you be able to use with your logic.

  • The ternaryModeCode is of a literal type "dark" | "system" | "light".

    When ternaryModeCode is set to system, the isDarkMode will use system theme, like of iOS and MacOS.

    Also, ternaryModeCode implicitly exports a type with type TernaryDarkMode = typeof ternaryDarkMode

Returned interface

  • The toggleTernaryDarkMode is a function to cycle ternaryModeCode between dark, system and light(in this order).
  • The setTernaryDarkMode accepts a parameter of type TernaryDarkMode and set it as ternaryModeCode.

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

NameTypeDefault valueDescription
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.

NameTypeDescription
defaultValueTernaryDarkModeThe default value for the dark mode.
initializeWithValuebooleanIf true (default), the hook will initialize reading localStorage. In SSR, you should set it to false, returning default values initially.
localStorageKeystringThe key for storing dark mode preference in local storage.

TernaryDarkModeReturn

Represents the return type of the useTernaryDarkMode hook.

NameTypeDescription
isDarkModebooleanThe current state of the dark mode.
setTernaryDarkModeDispatch<SetStateAction<TernaryDarkMode>>A function to set the dark mode state.
ternaryDarkModeTernaryDarkModeThe current state of the dark mode.
toggleTernaryDarkMode() => voidA 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,
  }
}