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:
11
hooks/use-has-mounted.ts
Normal file
11
hooks/use-has-mounted.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export const useHasMounted = () => {
|
||||
const [hasMounted, setHasMounted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setHasMounted(true);
|
||||
}, []);
|
||||
|
||||
return hasMounted;
|
||||
};
|
40
hooks/use-prefers-reduced-motion.ts
Normal file
40
hooks/use-prefers-reduced-motion.ts
Normal 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;
|
||||
};
|
@ -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){}}()`,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
Reference in New Issue
Block a user