Beautiful theme switch

This commit is contained in:
2022-10-16 15:59:08 +02:00
parent 2b3c4e2482
commit 068a3f8f1e
8 changed files with 122 additions and 37 deletions

View File

@ -10,15 +10,6 @@ interface ILayoutProps {
}
const Layout: NextPage<ILayoutProps> = ({ title, children }) => {
useEffect(() => {
if (typeof window !== "undefined") {
const theme = window.localStorage.getItem("theme");
if(!theme || !document) return;
document.documentElement.setAttribute("data-theme", theme);
}
}, []);
return <>
<Head>
<title>{title ?? "c0ntroller.de"}</title>

View File

@ -2,20 +2,11 @@
import type { NextPage } from "next";
import Link from "next/link";
import { Terminal, Sun, Moon } from "phosphor-react";
import ThemeSwitch from "./ThemeSwitch";
import styles from "../../styles/Blog/Navigation.module.scss";
const Navigation: NextPage<{}> = () => {
const switchTheme = () => {
if (typeof document === "undefined") return;
const current = document.documentElement.getAttribute("data-theme") || "dark";
const setTo = current === "dark" ? "light" : "dark";
document.documentElement.setAttribute("data-theme", setTo);
if (typeof window !== "undefined") window.localStorage.setItem("theme", setTo);
};
return <nav className={styles.navigation}>
<Link href={"/"}>
<a className={`nostyle ${styles.imgContainer}`}>
@ -29,10 +20,7 @@ const Navigation: NextPage<{}> = () => {
<div className={styles.navLink}><Link href={"/"}><a className="nostyle">About me</a></Link></div>
<div className={styles.spacer}></div>
<Terminal size={"1.5em"} />
<div className={styles.themeSwitch}>
<Sun className={styles.lightTheme} size={"1.5em"} onClick={switchTheme} />
<Moon className={styles.darkTheme} size={"1.5em"} onClick={switchTheme} />
</div>
<ThemeSwitch />
</nav>;
};

View File

@ -0,0 +1,53 @@
import type { NextPage } from "next";
import { useEffect, useState } from "react";
import { useTheme } from "next-themes";
import { Sun, Moon, FileJs } from "phosphor-react";
import styles from "../../styles/Blog/ThemeSwitch.module.scss";
interface FadeProperties {
sun?: string;
moon?: string;
}
const ThemeSwitch: NextPage<{ size?: string }> = ({ size }) => {
const [mounted, setMounted] = useState(false);
const [fadeProps, setFadeProps] = useState<FadeProperties>({});
const { theme, setTheme } = useTheme();
// Will be run when the component is rendered.
useEffect(() => {
setMounted(true);
}, []);
const switchTheme = (theme: string) => {
if (theme === "dark") setFadeProps({
sun: styles.fadeIn,
moon: styles.fadeOut
});
else setFadeProps({
sun: styles.fadeOut,
moon: styles.fadeIn
});
setTheme(theme);
};
if (!mounted) {
return <div className={styles.switch} title="Theme switching needs JS to be enabled.">
<FileJs size={size || "1.5em"} />
</div>;
}
const sunClasses = fadeProps.sun || (theme === "dark" ? styles.selected : undefined);
const moonClasses = fadeProps.moon || (theme === "light" ? styles.selected : undefined);
return <div className={styles.switch}>
<Sun size={size || "1.5em"} className={sunClasses} onClick={() => switchTheme("light")} />
<Moon size={size || "1.5em"} className={moonClasses} onClick={() => switchTheme("dark")} />
</div>;
};
export default ThemeSwitch;