Skip to content

useTernaryDarkMode

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

Usage

tsx
import { useTernaryDarkMode } from 'vhooks'

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 => {
            // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
            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>
  )
}

Installation

sh
pnpm dlx scaflo@latest https://raw.githubusercontent.com/programming-with-ia/vDocs/scaflos/hooks/useTernaryDarkMode.json -e %src%/hooks
sh
npx scaflo@latest https://raw.githubusercontent.com/programming-with-ia/vDocs/scaflos/hooks/useTernaryDarkMode.json -e %src%/hooks
sh
bunx scaflo@latest https://raw.githubusercontent.com/programming-with-ia/vDocs/scaflos/hooks/useTernaryDarkMode.json -e %src%/hooks
sh
yarn dlx scaflo@latest https://raw.githubusercontent.com/programming-with-ia/vDocs/scaflos/hooks/useTernaryDarkMode.json -e %src%/hooks

API

useTernaryDarkMode(options?): TernaryDarkModeReturn

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

Parameters

NameTypeDescription
options?TernaryDarkModeOptionsOptions or the local storage key for the hook.

Returns

TernaryDarkModeReturn

An object containing the dark mode state and helper functions.

Type aliases

Ƭ TernaryDarkMode: "system" | "dark" | "light"

Ternary dark mode options.

Ƭ TernaryDarkModeOptions: Object

Options for the useTernaryDarkMode hook.

Type declaration

NameTypeDescription
defaultValue?TernaryDarkModeThe default value for the dark mode. Default ts 'system'
initializeWithValue?booleanIf true (default), the hook will initialize reading localStorage. In SSR, you should set it to false, returning default values initially. Default ts true
localStorageKey?stringThe key for storing dark mode preference in local storage. Default ts 'vhooks-ternary-dark-mode'

Ƭ TernaryDarkModeReturn: Object

Represents the return type of the useTernaryDarkMode hook.

Type declaration

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() => void-

Hook

ts
import type { Dispatch, SetStateAction } from 'react'

import { useLocalStorage, useMediaQuery } from 'vhooks'

const COLOR_SCHEME_QUERY = '(prefers-color-scheme: dark)'
const LOCAL_STORAGE_KEY = 'vhooks-ternary-dark-mode'

export type TernaryDarkMode = 'system' | 'dark' | 'light'

export type TernaryDarkModeOptions = {
    defaultValue?: TernaryDarkMode
    localStorageKey?: string
    initializeWithValue?: boolean
}

export type TernaryDarkModeReturn = {
    isDarkMode: boolean
    ternaryDarkMode: TernaryDarkMode
    setTernaryDarkMode: Dispatch<SetStateAction<TernaryDarkMode>>
    toggleTernaryDarkMode: () => void
}

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): TernaryDarkMode => {
      const nextIndex = (modes.indexOf(prevMode) + 1) % modes.length
      return modes[nextIndex]
    })
  }

  return {
    isDarkMode,
    ternaryDarkMode: mode,
    setTernaryDarkMode: setMode,
    toggleTernaryDarkMode,
  }
}

vDocs