src/layouts/Base.astro 1.9 K raw
1
---
2
import type { SiteMeta } from "@/data/siteMeta";
3
import BaseHead from "@/components/BaseHead";
4
import Header from "@/components/layout/Header";
5
import Footer from "@/components/layout/Footer";
6
import SkipLink from "@/components/SkipLink";
7
import siteConfig from "@/site-config";
8
9
interface Props {
10
	meta: SiteMeta;
11
}
12
13
const {
14
	meta: { title, description = siteConfig.description, ogImage, articleDate },
15
} = Astro.props;
16
---
17
18
<html lang={siteConfig.lang}>
19
	<head>
20
		<BaseHead title={title} description={description} ogImage={ogImage} articleDate={articleDate} />
21
		<script define:vars={{ siteConfig }}>
22
			const root = document.documentElement;
23
			const colorThemeMetaTag = document.querySelector("meta[name='theme-color']");
24
25
			// get user preference of dark mode, 1st local storage, 2nd browser
26
			function getThemePreference() {
27
				if (typeof localStorage !== "undefined" && localStorage.getItem("theme")) {
28
					return localStorage.getItem("theme");
29
				}
30
				return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
31
			}
32
33
			const isDark = getThemePreference() === "dark";
34
35
			// watch document element class attribute and update user preference when it changes.
36
			const observer = new MutationObserver(() => {
37
				const rootIsDark = root.classList.contains("dark");
38
				// set the meta attribute
39
				colorThemeMetaTag.setAttribute(
40
					"content",
41
					siteConfig[rootIsDark ? "themeColorDark" : "themeColorLight"]
42
				);
43
				// store user preference
44
				if (typeof localStorage !== "undefined") {
45
					localStorage.setItem("theme", rootIsDark ? "dark" : "light");
46
				}
47
			});
48
			observer.observe(root, { attributeFilter: ["class"] });
49
50
			// initailse root class attribute
51
			root.classList.toggle("dark", isDark);
52
		</script>
53
	</head>
54
	<body>
55
		<SkipLink />
56
		<Header />
57
		<main id="main" class="flex-1">
58
			<slot />
59
		</main>
60
		<Footer />
61
	</body>
62
</html>