Skip to content

Instantly share code, notes, and snippets.

@gragland
Last active February 24, 2023 17:20
Show Gist options
  • Save gragland/cdaab58e8621be22301700e6a5d59498 to your computer and use it in GitHub Desktop.
Save gragland/cdaab58e8621be22301700e6a5d59498 to your computer and use it in GitHub Desktop.
// Usage
function App() {
const [darkMode, setDarkMode] = useDarkMode();
return (
<div>
<div className="navbar">
<Toggle darkMode={darkMode} setDarkMode={setDarkMode} />
</div>
<Content />
</div>
);
}
// Hook
function useDarkMode() {
// Use our useLocalStorage hook to persist state through a page refresh.
// Read the recipe for this hook to learn more: usehooks.com/useLocalStorage
const [enabledState, setEnabledState] = useLocalStorage('dark-mode-enabled');
// See if user has set a browser or OS preference for dark mode.
// The usePrefersDarkMode hook composes a useMedia hook (see code below).
const prefersDarkMode = usePrefersDarkMode();
// If enabledState is defined use it, otherwise fallback to prefersDarkMode.
// This allows user to override OS level setting on our website.
const enabled =
typeof enabledState !== 'undefined' ? enabledState : prefersDarkMode;
// Fire off effect that add/removes dark mode class
useEffect(
() => {
const className = 'dark-mode';
const element = window.document.body;
if (enabled) {
element.classList.add(className);
} else {
element.classList.remove(className);
}
},
[enabled] // Only re-call effect when value changes
);
// Return enabled state and setter
return [enabled, setEnabledState];
}
// Compose our useMedia hook to detect dark mode preference.
// The API for useMedia looks a bit weird, but that's because ...
// ... it was designed to support multiple media queries and return values.
// Thanks to hook composition we can hide away that extra complexity!
// Read the recipe for useMedia to learn more: usehooks.com/useMedia
function usePrefersDarkMode() {
return useMedia(['(prefers-color-scheme: dark)'], [true], false);
}
@lesleh
Copy link

lesleh commented Feb 24, 2023

This code:

if (enabled) {
  element.classList.add(className);
} else {
  element.classList.remove(className);
}

can be simplified to:

element.classList.toggle(className, enabled);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment