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
		<!-- Google tag (gtag.js) -->
21
		<BaseHead title={title} description={description} ogImage={ogImage} articleDate={articleDate} />
22
		<script define:vars={{ siteConfig }}>
23
			const root = document.documentElement;
24
			const colorThemeMetaTag = document.querySelector("meta[name='theme-color']");
25
26
			// get user preference of dark mode, 1st local storage, 2nd browser
27
			function getThemePreference() {
28
				if (typeof localStorage !== "undefined" && localStorage.getItem("theme")) {
29
					return localStorage.getItem("theme");
30
				}
31
				return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
32
			}
33
34
			const isDark = getThemePreference() === "dark";
35
36
			// watch document element class attribute and update user preference when it changes.
37
			const observer = new MutationObserver(() => {
38
				const rootIsDark = root.classList.contains("dark");
39
				// set the meta attribute
40
				colorThemeMetaTag.setAttribute(
41
					"content",
42
					siteConfig[rootIsDark ? "themeColorDark" : "themeColorLight"]
43
				);
44
				// store user preference
45
				if (typeof localStorage !== "undefined") {
46
					localStorage.setItem("theme", rootIsDark ? "dark" : "light");
47
				}
48
			});
49
			observer.observe(root, { attributeFilter: ["class"] });
50
51
			// initailse root class attribute
52
			root.classList.toggle("dark", isDark);
53
		</script>
54
	</head>
55
	<body>
56
		<SkipLink />
57
		<Header />
58
    <main id="main" class="flex-1" transition:animate="slide">
59
			<slot />
60
		</main>
61
		<Footer />
62
	</body>
63
</html>