summaryrefslogtreecommitdiff
path: root/src/components/ThemeToggle.astro
blob: 7621daf4945531690957b5f1749140c2a0adda12 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<theme-toggle class="ms-2 sm:ms-4">
	<button class="hover:text-accent relative h-9 w-9 cursor-pointer rounded-md p-2" type="button">
		<span class="sr-only">Dark Theme</span>
		<svg
			aria-hidden="true"
			class="absolute start-1/2 top-1/2 h-7 w-7 -translate-x-1/2 -translate-y-1/2 scale-100 opacity-100 transition-all dark:scale-0 dark:opacity-0"
			fill="none"
			focusable="false"
			id="sun-svg"
			stroke-width="1.5"
			viewBox="0 0 24 24"
			xmlns="http://www.w3.org/2000/svg"
		>
			<path
				d="M12 18C15.3137 18 18 15.3137 18 12C18 8.68629 15.3137 6 12 6C8.68629 6 6 8.68629 6 12C6 15.3137 8.68629 18 12 18Z"
				stroke="currentColor"
				stroke-linecap="round"
				stroke-linejoin="round"></path>
			<path d="M22 12L23 12" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
			></path>
			<path d="M12 2V1" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
			<path d="M12 23V22" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
			></path>
			<path d="M20 20L19 19" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
			></path>
			<path d="M20 4L19 5" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
			></path>
			<path d="M4 20L5 19" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
			></path>
			<path d="M4 4L5 5" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
			></path>
			<path d="M1 12L2 12" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
			></path>
		</svg>
		<svg
			aria-hidden="true"
			class="absolute start-1/2 top-1/2 h-7 w-7 -translate-x-1/2 -translate-y-1/2 scale-0 opacity-0 transition-all dark:scale-100 dark:opacity-100"
			fill="none"
			focusable="false"
			id="moon-svg"
			stroke="currentColor"
			stroke-width="1.5"
			viewBox="0 0 24 24"
			xmlns="http://www.w3.org/2000/svg"
		>
			<path d="M0 0h24v24H0z" fill="none" stroke="none"></path>
			<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"
			></path>
			<path d="M17 4a2 2 0 0 0 2 2a2 2 0 0 0 -2 2a2 2 0 0 0 -2 -2a2 2 0 0 0 2 -2"></path>
			<path d="M19 11h2m-1 -1v2"></path>
		</svg>
	</button>
</theme-toggle>

<script>
	// Note that if you fire the theme-change event outside of this component, it will not be reflected in the button's aria-checked attribute. You will need to add an event listener if you want that.
	import { rootInDarkMode } from "@/utils/domElement";

	class ThemeToggle extends HTMLElement {
		constructor() {
			super();
			const button = this.querySelector<HTMLButtonElement>("button");

			if (button) {
				// set aria role value
				button.setAttribute("role", "switch");
				button.setAttribute("aria-checked", String(rootInDarkMode()));

				// button event
				button.addEventListener("click", () => {
					// invert theme
					let themeChangeEvent = new CustomEvent("theme-change", {
						detail: {
							theme: rootInDarkMode() ? "light" : "dark",
						},
					});
					// dispatch event -> ThemeProvider.astro
					document.dispatchEvent(themeChangeEvent);

					// set the aria-checked attribute
					button.setAttribute("aria-checked", String(rootInDarkMode()));
				});
			} else {
				console.warn("Theme Toggle: No button found");
			}
		}
	}

	customElements.define("theme-toggle", ThemeToggle);
</script>