feat: theme toggle

This commit is contained in:
not-nullptr 2024-11-13 18:54:05 +00:00
parent 6c955e33e3
commit 6bb920592d
6 changed files with 53 additions and 1 deletions

View File

@ -42,6 +42,7 @@
"clsx": "^2.1.1",
"lucide-svelte": "^0.456.0",
"svelte-adapter-bun": "^0.5.2",
"typescript-cookie": "^1.0.6",
"wasm-vips": "^0.0.11"
}
}

View File

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<body data-sveltekit-preload-data="hover" class="%theme%">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>

9
src/hooks.server.ts Normal file
View File

@ -0,0 +1,9 @@
import type { Handle } from "@sveltejs/kit";
export const handle: Handle = async ({ event, resolve }) => {
const theme = event.cookies.get("theme") ?? "";
const res = await resolve(event, {
transformPageChunk: ({ html }) => html.replace("%theme%", theme),
});
return res;
};

View File

@ -21,6 +21,7 @@ class Theme {
public dark = $state(false);
public toggle = () => {
this.dark = !this.dark;
console.log(this.dark);
};
}

View File

@ -9,6 +9,9 @@
import { PUB_HOSTNAME, PUB_PLAUSIBLE_URL } from "$env/static/public";
import FancyMenu from "$lib/components/functional/FancyMenu.svelte";
import { writable } from "svelte/store";
import { SunIcon } from "lucide-svelte";
import { browser } from "$app/environment";
import { setCookie } from "typescript-cookie";
let { children, data } = $props();
let shouldGoBack = writable(false);
@ -46,6 +49,23 @@
goto("/");
}
};
$effect(() => {
if (!browser) return;
if (theme.dark) {
document.body.classList.add("dark");
document.body.classList.remove("light");
setCookie("theme", "dark", {
sameSite: "strict",
});
} else {
document.body.classList.add("light");
document.body.classList.remove("dark");
setCookie("theme", "light", {
sameSite: "strict",
});
}
});
</script>
<svelte:head>
@ -91,6 +111,11 @@
</div>
<FancyMenu {links} {shouldGoBack} />
<div class="h-16 px-4 flex items-center">
<button onclick={theme.toggle}>
<SunIcon />
</button>
</div>
</div>
<div class="w-full max-w-screen-lg grid grid-cols-1 grid-rows-1 relative">
{#key data.pathname}

16
src/routes/+layout.ts Normal file
View File

@ -0,0 +1,16 @@
import { browser } from "$app/environment";
import { theme } from "$lib/store/index.svelte";
import { getCookie, setCookie } from "typescript-cookie";
export const load = ({ data }) => {
if (!browser) return;
const themeStr = getCookie("theme");
if (typeof themeStr === "undefined") {
theme.dark = window.matchMedia("(prefers-color-scheme: dark)").matches;
setCookie("theme", theme.dark ? "dark" : "light");
} else {
theme.dark = themeStr === "dark";
}
theme.dark = getCookie("theme") === "dark";
return data;
};