|
21 | 21 | </style> |
22 | 22 |
|
23 | 23 | <script is:inline> |
24 | | - const applyThemeFromLocalStorage = () => { |
25 | | - const theme = |
26 | | - (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) || |
27 | | - 'light'; |
28 | | - if (theme === 'dark') { |
29 | | - document.documentElement.classList.add('dark'); |
| 24 | + const applyThemeFromLocalStorage = () => { |
| 25 | + const theme = localStorage?.getItem("theme") ?? "light"; |
| 26 | + if (theme === "dark") { |
| 27 | + document.documentElement.classList.add("dark"); |
30 | 28 | } else { |
31 | | - document.documentElement.classList.remove('dark'); |
| 29 | + document.documentElement.classList.remove("dark"); |
32 | 30 | } |
33 | 31 | }; |
34 | 32 |
|
| 33 | + const getInitialTheme = () => { |
| 34 | + const stored = localStorage?.getItem("theme") ?? ""; |
| 35 | + if (["dark", "light"].includes(stored)) return stored; |
| 36 | + return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; |
| 37 | + }; |
35 | 38 |
|
36 | | - const theme = (() => { |
37 | | - const localStorageTheme = localStorage?.getItem("theme") ?? ''; |
38 | | - if (['dark', 'light'].includes(localStorageTheme)) { |
39 | | - return localStorageTheme; |
40 | | - } |
41 | | - if (window.matchMedia('(prefers-color-scheme: dark)').matches) { |
42 | | - return 'dark'; |
43 | | - } |
44 | | - return 'light'; |
45 | | - })(); |
46 | | - |
47 | | - if (theme === 'light') { |
48 | | - document.body.classList.remove('dark'); |
| 39 | + // Initial theme application |
| 40 | + const theme = getInitialTheme(); |
| 41 | + localStorage.setItem("theme", theme); |
| 42 | + if (theme === "dark") { |
| 43 | + document.documentElement.classList.add("dark"); |
49 | 44 | } else { |
50 | | - document.body.classList.add('dark'); |
| 45 | + document.documentElement.classList.remove("dark"); |
51 | 46 | } |
52 | 47 |
|
53 | | - window.localStorage.setItem('theme', theme); |
54 | | - |
55 | 48 | const handleToggleClick = () => { |
56 | | - const element = document.body; |
57 | | - element.classList.toggle("dark"); |
58 | | - |
59 | | - const isDark = element.classList.contains("dark"); |
| 49 | + const html = document.documentElement; |
| 50 | + const isDark = html.classList.toggle("dark"); |
60 | 51 | localStorage.setItem("theme", isDark ? "dark" : "light"); |
61 | | - } |
62 | | - |
63 | | - document.getElementById("themeToggle")?.addEventListener("click", handleToggleClick); |
| 52 | + }; |
64 | 53 |
|
| 54 | + const setupThemeToggleButton = () => { |
| 55 | + const btn = document.getElementById("themeToggle"); |
| 56 | + if (!btn) return; |
65 | 57 |
|
66 | | - const setupThemeToggleButton = () => { |
67 | | - const toggleButton = document.getElementById("themeToggle"); |
68 | | - if (toggleButton) { |
69 | | - toggleButton.removeEventListener('click', handleToggleClick); // Prevent duplicate listeners |
70 | | - toggleButton.addEventListener('click', handleToggleClick); |
71 | | - } |
| 58 | + // Avoid duplicate listeners |
| 59 | + btn.removeEventListener("click", handleToggleClick); |
| 60 | + btn.addEventListener("click", handleToggleClick); |
72 | 61 | }; |
73 | 62 |
|
74 | | - // For View Transitions: Apply theme *immediately* after new DOM is swapped. |
75 | | - document.addEventListener('astro:after-swap', applyThemeFromLocalStorage); |
76 | | - |
77 | | - // For initial load and re-attaching button listener after page transitions: |
78 | | - if (document.readyState === 'loading') { |
79 | | - // Ensures button listener is attached after initial DOM is ready. |
80 | | - // Theme is already applied by the inline script in <head> of BaseLayout.astro for initial paint. |
81 | | - document.addEventListener('DOMContentLoaded', setupThemeToggleButton); |
| 63 | + // Attach theme toggle logic on initial page load |
| 64 | + if (document.readyState === "loading") { |
| 65 | + document.addEventListener("DOMContentLoaded", setupThemeToggleButton); |
82 | 66 | } else { |
83 | | - setupThemeToggleButton(); // If script loads after DOMContentLoaded. |
| 67 | + setupThemeToggleButton(); |
84 | 68 | } |
85 | | - // astro:page-load is for scripts that need to run after the page is fully loaded and painted. |
86 | | - // Good for re-attaching listeners to elements that might have been re-rendered. |
87 | | - document.addEventListener('astro:page-load', setupThemeToggleButton); |
88 | 69 |
|
| 70 | + // View Transition: Reapply theme & reattach toggle after DOM is swapped |
| 71 | + document.addEventListener("astro:after-swap", () => { |
| 72 | + applyThemeFromLocalStorage(); |
| 73 | + setupThemeToggleButton(); |
| 74 | + }); |
| 75 | + |
| 76 | + // Optional: useful for certain components being delayed |
| 77 | + document.addEventListener("astro:page-load", setupThemeToggleButton); |
89 | 78 | </script> |
| 79 | + |
0 commit comments