Browse Source

Take system's theme for the beta site (#4022)

* Take system's theme for the site

* Add IIFE for dark mode in document load and preserve in localStorage

* Add types

* Fix SSR and respect override

Co-authored-by: Dan Abramov <dan.abramov@me.com>
main
harish-sethuraman 3 years ago
committed by GitHub
parent
commit
5ba0ad88b8
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 65
      beta/src/components/Layout/Nav/Nav.tsx
  2. 43
      beta/src/pages/_document.tsx

65
beta/src/components/Layout/Nav/Nav.tsx

@ -15,6 +15,13 @@ import {MenuContext} from 'components/useMenu';
import {Logo} from '../../Logo'; import {Logo} from '../../Logo';
import NavLink from './NavLink'; import NavLink from './NavLink';
declare global {
interface Window {
__theme: string;
__setPreferredTheme: (theme: string) => void;
}
}
const feedbackIcon = ( const feedbackIcon = (
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -92,14 +99,6 @@ function inferSection(pathname: string): 'learn' | 'reference' | 'home' {
export default function Nav() { export default function Nav() {
const {pathname} = useRouter(); const {pathname} = useRouter();
const {isOpen, toggleOpen} = React.useContext(MenuContext); const {isOpen, toggleOpen} = React.useContext(MenuContext);
// TODO: persist
// TODO: respect system pref
const [isDark, setIsDark] = React.useState(() => {
if (typeof document === 'undefined') {
return false;
}
return document.documentElement.classList.contains('dark');
});
const section = inferSection(pathname); const section = inferSection(pathname);
function handleFeedback() { function handleFeedback() {
@ -137,22 +136,29 @@ export default function Nav() {
Beta Beta
</div> </div>
</div> </div>
<div className="block dark:hidden">
<button <button
type="button" type="button"
aria-label={isDark ? 'Use Light Mode' : 'Use Dark Mode'} aria-label="Use Dark Mode"
onClick={() => { onClick={() => {
if (isDark) { window.__setPreferredTheme('dark');
document.documentElement.classList.remove('dark'); }}
setIsDark(false); className="hidden lg:flex items-center h-full pr-2">
} else { {darkIcon}
document.documentElement.classList.add('dark'); </button>
setIsDark(true); </div>
} <div className="hidden dark:block">
<button
type="button"
aria-label="Use Light Mode"
onClick={() => {
window.__setPreferredTheme('light');
}} }}
className="hidden lg:flex items-center h-full pr-2"> className="hidden lg:flex items-center h-full pr-2">
{isDark ? lightIcon : darkIcon} {lightIcon}
</button> </button>
</div> </div>
</div>
<div className="px-0 pt-2 w-full 2xl:max-w-xs hidden lg:flex items-center self-center border-b-0 lg:border-b border-border dark:border-border-dark"> <div className="px-0 pt-2 w-full 2xl:max-w-xs hidden lg:flex items-center self-center border-b-0 lg:border-b border-border dark:border-border-dark">
<NavLink href="/" isActive={section === 'home'}> <NavLink href="/" isActive={section === 'home'}>
Home Home
@ -172,22 +178,29 @@ export default function Nav() {
onClick={handleFeedback}> onClick={handleFeedback}>
{feedbackIcon} {feedbackIcon}
</button> </button>
<div className="block dark:hidden">
<button <button
type="button" type="button"
aria-label={isDark ? 'Use Light Mode' : 'Use Dark Mode'} aria-label="Use Dark Mode"
onClick={() => { onClick={() => {
if (isDark) { window.__setPreferredTheme('dark');
document.documentElement.classList.remove('dark'); }}
setIsDark(false); className="flex lg:hidden items-center p-1 h-full ml-4 lg:ml-6">
} else { {darkIcon}
document.documentElement.classList.add('dark'); </button>
setIsDark(true); </div>
} <div className="hidden dark:block">
<button
type="button"
aria-label="Use Light Mode"
onClick={() => {
window.__setPreferredTheme('light');
}} }}
className="flex lg:hidden items-center p-1 h-full ml-4 lg:ml-6"> className="flex lg:hidden items-center p-1 h-full ml-4 lg:ml-6">
{isDark ? lightIcon : darkIcon} {lightIcon}
</button> </button>
</div> </div>
</div>
</nav> </nav>
); );
} }

43
beta/src/pages/_document.tsx

@ -12,6 +12,49 @@ class MyDocument extends Document {
<Html lang="en"> <Html lang="en">
<Head /> <Head />
<body className="font-sans antialiased text-lg bg-wash dark:bg-wash-dark text-secondary dark:text-secondary-dark leading-base"> <body className="font-sans antialiased text-lg bg-wash dark:bg-wash-dark text-secondary dark:text-secondary-dark leading-base">
<script
dangerouslySetInnerHTML={{
__html: `
(function () {
function setTheme(newTheme) {
window.__theme = newTheme;
if (newTheme === 'dark') {
document.documentElement.classList.add('dark');
} else if (newTheme === 'light') {
document.documentElement.classList.remove('dark');
}
}
var preferredTheme;
try {
preferredTheme = localStorage.getItem('theme');
} catch (err) { }
window.__setPreferredTheme = function(newTheme) {
preferredTheme = newTheme;
setTheme(newTheme);
try {
localStorage.setItem('theme', newTheme);
} catch (err) { }
};
var initialTheme = preferredTheme;
var darkQuery = window.matchMedia('(prefers-color-scheme: dark)');
if (!initialTheme) {
initialTheme = darkQuery.matches ? 'dark' : 'light';
}
setTheme(initialTheme);
darkQuery.addListener(function (e) {
if (!preferredTheme) {
setTheme(e.matches ? 'dark' : 'light');
}
});
})();
`,
}}
/>
<Main /> <Main />
<NextScript /> <NextScript />
</body> </body>

Loading…
Cancel
Save