Skip to content

Instantly share code, notes, and snippets.

@zaydek-old
Last active October 28, 2019 07:02
Show Gist options
  • Save zaydek-old/4a7cddbafb3dc4510b787eb33ecb750f to your computer and use it in GitHub Desktop.
Save zaydek-old/4a7cddbafb3dc4510b787eb33ecb750f to your computer and use it in GitHub Desktop.
How I implemented dark mode on the unreleased preview of Codex.
// ...
// This is how I’m using `useDarkMode` in practice:
const [darkMode, setDarkMode] = useDarkMode()
React.useEffect(() => {
const html = document.querySelector("html")
if (darkMode) {
// Update the CSS variables:
html.setAttribute("data-dark-mode", "")
} else {
// Revert the CSS variables:
html.removeAttribute("data-dark-mode")
}
}, [darkMode])
// ...
/* webkit.org/blog/8840/dark-mode-support-in-webkit */
:root { color-scheme: light dark; }
html {
--text: 000, 00.0%, 000.0%;
--base: 000, 00.0%, 100.0%;
--blue: 217, 97.0%, 064.0%;
--gray: 000, 00.0%, 062.5%;
--code-base: 000, 00.0%, 097.5%;
--code-trim: 000, 00.0%, 092.5%;
--bars-base: 000, 00.0%, 095.0%;
}
html[data-dark-mode] {
--text: 000, 00.0%, 090.0%;
--base: 000, 00.0%, 010.0%;
--blue: 217, 97.0%, 064.0%;
--gray: 000, 00.0%, 062.5%;
--code-base: 000, 00.0%, 015.0%;
--code-trim: 000, 00.0%, 025.0%;
--bars-base: 000, 00.0%, 022.5%;
}
.c\:text { color: hsl(var(--text)); }
.c\:base { color: hsl(var(--base)); }
.c\:blue { color: hsl(var(--blue)); }
.c\:gray { color: hsl(var(--gray)); }
.c\:code-base { color: hsl(var(--code-base)); }
.c\:code-trim { color: hsl(var(--code-trim)); }
.c\:bars-base { color: hsl(var(--bars-base)); }
.b\:text { background: hsl(var(--text)); }
.b\:base { background: hsl(var(--base)); }
.b\:blue { background: hsl(var(--blue)); }
.b\:gray { background: hsl(var(--gray)); }
.b\:code-base { background: hsl(var(--code-base)); }
.b\:code-trim { background: hsl(var(--code-trim)); }
.b\:bars-base { background: hsl(var(--bars-base)); }
import React from "react"
function useDarkMode() {
const [darkMode, setDarkMode] = React.useState(false)
// Prefer `useLayoutEffect` because we want to eagerly
// compute dark mode.
React.useLayoutEffect(() => {
const media = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)")
const computeMode = () => {
setDarkMode(media && media.matches)
}
// First render:
computeMode()
// `addListener` works like `addEventListener`.
media.addListener(computeMode)
// Cleanup function: remove listener when component is
// unmounted.
return () => {
media.removeListener(computeMode)
}
}, [])
return [darkMode, setDarkMode]
}
export default useDarkMode
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment