diff --git a/components/Blog/Layout.tsx b/components/Blog/Layout.tsx index 4537008..a14fb42 100644 --- a/components/Blog/Layout.tsx +++ b/components/Blog/Layout.tsx @@ -10,15 +10,6 @@ interface ILayoutProps { } const Layout: NextPage = ({ title, children }) => { - - useEffect(() => { - if (typeof window !== "undefined") { - const theme = window.localStorage.getItem("theme"); - if(!theme || !document) return; - document.documentElement.setAttribute("data-theme", theme); - } - }, []); - return <> {title ?? "c0ntroller.de"} diff --git a/components/Blog/Navigation.tsx b/components/Blog/Navigation.tsx index 99e5737..a12bd3d 100644 --- a/components/Blog/Navigation.tsx +++ b/components/Blog/Navigation.tsx @@ -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 ; }; diff --git a/components/Blog/ThemeSwitch.tsx b/components/Blog/ThemeSwitch.tsx new file mode 100644 index 0000000..c7e5c28 --- /dev/null +++ b/components/Blog/ThemeSwitch.tsx @@ -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({}); + 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
+ +
; + } + + const sunClasses = fadeProps.sun || (theme === "dark" ? styles.selected : undefined); + const moonClasses = fadeProps.moon || (theme === "light" ? styles.selected : undefined); + + return
+ switchTheme("light")} /> + switchTheme("dark")} /> +
; + +}; + +export default ThemeSwitch; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index c995e72..63dcd89 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "color": "^4.2.3", "highlight.js": "^11.5.1", "next": "12.1.0", + "next-themes": "^0.2.1", "node-fetch": "^3.2.0", "phosphor-react": "^1.3.1", "react": "17.0.2", @@ -3075,6 +3076,16 @@ } } }, + "node_modules/next-themes": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.2.1.tgz", + "integrity": "sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==", + "peerDependencies": { + "next": "*", + "react": "*", + "react-dom": "*" + } + }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -6708,6 +6719,12 @@ "use-subscription": "1.5.1" } }, + "next-themes": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.2.1.tgz", + "integrity": "sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==", + "requires": {} + }, "node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", diff --git a/package.json b/package.json index fc428cf..92a73df 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "color": "^4.2.3", "highlight.js": "^11.5.1", "next": "12.1.0", + "next-themes": "^0.2.1", "node-fetch": "^3.2.0", "phosphor-react": "^1.3.1", "react": "17.0.2", diff --git a/pages/_app.tsx b/pages/_app.tsx index e48b447..ce70223 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -1,5 +1,6 @@ import type { AppProps } from "next/app"; import Head from "next/head"; +import { ThemeProvider } from "next-themes"; import "../styles/globals.scss"; import { CommandsProvider } from "../lib/commands/ContextProvider"; import { ModalFunctionProvider } from "../components/Terminal/contexts/ModalFunctions"; @@ -33,11 +34,13 @@ function MyApp({ Component, pageProps }: AppProps) { - - - - - + + + + + + + ; } diff --git a/styles/Blog/Navigation.module.scss b/styles/Blog/Navigation.module.scss index 2e69d70..6bfc232 100644 --- a/styles/Blog/Navigation.module.scss +++ b/styles/Blog/Navigation.module.scss @@ -54,13 +54,4 @@ .spacer { flex-grow: 2; } - - .themeSwitch { - .lightTheme { - display: var(--blog_dark-el-display) - } - .darkTheme { - display: var(--blog_light-el-display) - } - } } \ No newline at end of file diff --git a/styles/Blog/ThemeSwitch.module.scss b/styles/Blog/ThemeSwitch.module.scss new file mode 100644 index 0000000..d322f80 --- /dev/null +++ b/styles/Blog/ThemeSwitch.module.scss @@ -0,0 +1,41 @@ +.switch { + position: relative; + width: 1.5em; + height: 1.5em; + + & > * { + position: absolute; + } + + .fadeOut { + animation: fadeOut 0.2s ease-in-out; + animation-fill-mode: forwards; + } + + .fadeIn { + animation: fadeIn 0.2s ease-in-out; + animation-fill-mode: forwards; + } +} + +@keyframes fadeOut { + from { + opacity: 1; + transform: translate(0, 0); + } + to { + opacity: 0; + transform: translate(0, -100%); + } +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translate(0, 100%); + } + to { + opacity: 1; + transform: translate(0, 0); + } +} \ No newline at end of file