1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2025-06-30 23:21:29 -04:00

animated dark mode toggle 🌓

This commit is contained in:
2022-03-07 19:32:43 -05:00
parent 19394c1fb7
commit f5c8a7a21a
8 changed files with 229 additions and 31 deletions

11
hooks/use-has-mounted.ts Normal file
View File

@ -0,0 +1,11 @@
import { useEffect, useState } from "react";
export const useHasMounted = () => {
const [hasMounted, setHasMounted] = useState(false);
useEffect(() => {
setHasMounted(true);
}, []);
return hasMounted;
};

View File

@ -0,0 +1,40 @@
// SSR-safe reduced motion hook:
// https://www.joshwcomeau.com/react/prefers-reduced-motion/#ssr-safety
import { useEffect, useState } from "react";
const QUERY = "(prefers-reduced-motion: no-preference)";
export const usePrefersReducedMotion = (): boolean => {
// default to no animations on server-side
const [prefersReducedMotion, setPrefersReducedMotion] = useState(true);
useEffect(() => {
// this can now be safely set for the first time on the client-side
setPrefersReducedMotion(!window.matchMedia(QUERY).matches);
// register a listener for changes
const listener = (event: MediaQueryListEvent) => {
setPrefersReducedMotion(!event.matches);
};
const mediaQueryList = window.matchMedia(QUERY);
if (mediaQueryList.addEventListener) {
mediaQueryList.addEventListener("change", listener);
} else {
// support deprecated listener API
mediaQueryList.addListener(listener);
}
// clean up the event listener
return () => {
if (mediaQueryList.removeEventListener) {
mediaQueryList.removeEventListener("change", listener);
} else {
mediaQueryList.removeListener(listener);
}
};
}, [setPrefersReducedMotion]);
return prefersReducedMotion;
};

View File

@ -238,8 +238,6 @@ const ThemeScript = memo(
<script
key="next-themes-script"
dangerouslySetInnerHTML={{
// These are minified via Terser and then updated by hand, don't recommend
// prettier-ignore
__html: `!function(){${optimization}${updateDOM(forcedTheme)}}()`,
}}
/>
@ -247,8 +245,14 @@ const ThemeScript = memo(
<script
key="next-themes-script"
dangerouslySetInnerHTML={{
// prettier-ignore
__html: `!function(){try {${optimization}var e=localStorage.getItem("${storageKey}");${!defaultSystem ? updateDOM(defaultTheme) + ";" : ""}if("system"===e||(!e&&${defaultSystem})){var t="${MEDIA}",m=window.matchMedia(t);m.media!==t||m.matches?${updateDOM("dark")}:${updateDOM("light")}}else if(e) ${value ? `var x=${JSON.stringify(value)};` : ""}${updateDOM(value ? "x[e]" : "e", true)}}catch(e){}}()`,
__html: `!function(){try{${optimization}var e=localStorage.getItem("${storageKey}");${
!defaultSystem ? updateDOM(defaultTheme) + ";" : ""
}if("system"===e||(!e&&${defaultSystem})){var t="${MEDIA}",m=window.matchMedia(t);m.media!==t||m.matches?${updateDOM(
"dark"
)}:${updateDOM("light")}}else if(e){${value ? `var x=${JSON.stringify(value)}` : ""}}${updateDOM(
value ? "x[e]" : "e",
true
)}}catch(e){}}()`,
}}
/>
)}