useTernaryDarkMode()
This React Hook offers you an interface to toggle and read the dark theme mode between three values. It uses internally useLocalStorage()
to persist the value and listens the OS color scheme preferences.
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 tosystem
, theisDarkMode
will use system theme, like of iOS and MacOS.Also,
ternaryModeCode
implicitly exports a type withtype TernaryDarkMode = typeof ternaryDarkMode
Returned interface
- The
toggleTernaryDarkMode
is a function to cycleternaryModeCode
betweendark
,system
andlight
(in this order). - The
setTernaryDarkMode
accepts a parameter of typeTernaryDarkMode
and set it asternaryModeCode
.
The Hook
1import { Dispatch, SetStateAction, useEffect, useState } from 'react'23import { useLocalStorage, useMediaQuery, useUpdateEffect } from 'usehooks-ts'45const COLOR_SCHEME_QUERY = '(prefers-color-scheme: dark)'67type TernaryDarkMode = 'system' | 'dark' | 'light'8interface UseTernaryDarkModeOutput {9 isDarkMode: boolean10 ternaryDarkMode: TernaryDarkMode11 setTernaryDarkMode: Dispatch<SetStateAction<TernaryDarkMode>>12 toggleTernaryDarkMode: () => void13}1415function useTernaryDarkMode(): UseTernaryDarkModeOutput {16 const isDarkOS = useMediaQuery(COLOR_SCHEME_QUERY)17 const [ternaryDarkMode, setTernaryDarkMode] =18 useLocalStorage<TernaryDarkMode>('usehooks-ts-ternary-dark-mode', 'system')19 const [isDarkMode, setDarkMode] = useState<boolean>(isDarkOS)2021 // Update darkMode if os prefers changes22 useUpdateEffect(() => {23 if (ternaryDarkMode === 'system') {24 setDarkMode(isDarkOS)25 }26 }, [isDarkOS])2728 useEffect(() => {29 switch (ternaryDarkMode) {30 case 'light':31 setDarkMode(false)32 break33 case 'system':34 setDarkMode(isDarkOS)35 break36 case 'dark':37 setDarkMode(true)38 break39 }40 }, [ternaryDarkMode, isDarkOS])4142 function toggleTernaryDarkMode() {43 const toggleDict: Record<TernaryDarkMode, TernaryDarkMode> = {44 light: 'system',45 system: 'dark',46 dark: 'light',47 }48 setTernaryDarkMode(prevMode => toggleDict[prevMode])49 }5051 return {52 isDarkMode,53 ternaryDarkMode,54 setTernaryDarkMode,55 toggleTernaryDarkMode,56 }57}5859export default useTernaryDarkMode
Usage
1import { useTernaryDarkMode } from 'usehooks-ts'23export default function Component() {4 const {5 isDarkMode,6 ternaryDarkMode,7 setTernaryDarkMode,8 toggleTernaryDarkMode,9 } = useTernaryDarkMode()10 type TernaryDarkMode = typeof ternaryDarkMode1112 return (13 <div>14 <p>Current theme: {isDarkMode ? 'dark' : 'light'}</p>15 <p>ternaryMode: {ternaryDarkMode}</p>16 <p>17 Toggle between three modes18 <button onClick={toggleTernaryDarkMode}>19 Toggle from {ternaryDarkMode}20 </button>21 </p>22 <p>23 Select a mode24 <br />25 <select26 name="select-ternaryDarkMode"27 onChange={ev =>28 setTernaryDarkMode(ev.target.value as TernaryDarkMode)29 }30 value={ternaryDarkMode}31 >32 <option value="light">light</option>33 <option value="system">system</option>34 <option value="dark">dark</option>35 </select>36 </p>37 </div>38 )39}
See a way to make this page better?
Edit there »