src/components/ThemeToggle.astro 3.6 K raw
1
<script>
2
	class ThemeToggle extends HTMLElement {
3
		constructor() {
4
			super();
5
			const button = this.querySelector("button") as HTMLButtonElement;
6
7
			function setTheme(dark: boolean) {
8
				// This could/should be a CustomEvent()
9
				document.documentElement.classList.toggle("dark", dark);
10
				// set the aria-pressed attribute, dark mode === aria-pressed=true
11
				button.setAttribute("aria-pressed", String(dark));
12
			}
13
14
			// button clicked, toggle dark mode
15
			button.addEventListener("click", () => setTheme(!this.isDark()));
16
17
			// Initalise button state
18
			setTheme(this.isDark());
19
		}
20
21
		// returns if the root element contains the dark class
22
		isDark() {
23
			return document.documentElement.classList.contains("dark");
24
		}
25
	}
26
27
	customElements.define("theme-toggle", ThemeToggle);
28
</script>
29
30
<theme-toggle class="ml-auto">
31
	<button
32
		type="button"
33
		id="toggle-theme"
34
		class="group relative h-9 w-9 rounded-md bg-[#ECE0BB] p-2 ring-zinc-400 transition-all hover:ring-2 dark:bg-[#282828]"
35
		aria-label="Toggle Dark Mode"
36
	>
37
		<svg
38
			id="sun-svg"
39
			class="absolute top-1/2 left-1/2 h-7 w-7 -translate-x-1/2 -translate-y-1/2 scale-0 opacity-0 transition-all group-aria-pressed:scale-100 group-aria-pressed:opacity-100"
40
			aria-hidden="true"
41
			focusable="false"
42
			stroke-width="1.5"
43
			viewBox="0 0 24 24"
44
			fill="none"
45
			xmlns="http://www.w3.org/2000/svg"
46
		>
47
			<path
48
				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"
49
				stroke="currentColor"
50
				stroke-linecap="round"
51
				stroke-linejoin="round"></path>
52
			<path d="M22 12L23 12" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
53
			></path>
54
			<path d="M12 2V1" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
55
			<path d="M12 23V22" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
56
			></path>
57
			<path d="M20 20L19 19" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
58
			></path>
59
			<path d="M20 4L19 5" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
60
			></path>
61
			<path d="M4 20L5 19" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
62
			></path>
63
			<path d="M4 4L5 5" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
64
			></path>
65
			<path d="M1 12L2 12" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
66
			></path>
67
		</svg>
68
		<svg
69
			id="moon-svg"
70
			class="absolute top-1/2 left-1/2 h-7 w-7 -translate-x-1/2 -translate-y-1/2 scale-0 opacity-0 transition-all group-aria-[pressed=false]:scale-100 group-aria-[pressed=false]:opacity-100"
71
			aria-hidden="true"
72
			focusable="false"
73
			stroke-width="1.5"
74
			viewBox="0 0 24 24"
75
			fill="none"
76
			xmlns="http://www.w3.org/2000/svg"
77
		>
78
			<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="1.5"></circle>
79
			<path
80
				d="M7.63262 3.06689C8.98567 3.35733 9.99999 4.56025 9.99999 6.00007C9.99999 7.65693 8.65685 9.00007 6.99999 9.00007C5.4512 9.00007 4.17653 7.82641 4.01685 6.31997"
81
				stroke="currentColor"
82
				stroke-width="1.5"></path>
83
			<path
84
				d="M22 13.0505C21.3647 12.4022 20.4793 12 19.5 12C17.567 12 16 13.567 16 15.5C16 17.2632 17.3039 18.7219 19 18.9646"
85
				stroke="currentColor"
86
				stroke-width="1.5"></path>
87
			<path
88
				d="M14.5 8.51L14.51 8.49889"
89
				stroke="currentColor"
90
				stroke-linecap="round"
91
				stroke-linejoin="round"></path>
92
			<path
93
				d="M10 17C11.1046 17 12 16.1046 12 15C12 13.8954 11.1046 13 10 13C8.89543 13 8 13.8954 8 15C8 16.1046 8.89543 17 10 17Z"
94
				stroke="currentColor"
95
				stroke-linecap="round"
96
				stroke-linejoin="round"></path>
97
		</svg>
98
	</button>
99
</theme-toggle>