@@ -38,52 +38,79 @@ const { defaultThemeIdJson, darkThemeIdJson, metaColorsJson } = themeData()
3838 const darkThemeId = JSON.parse(darkThemeIdJson)
3939 const themeMetaColors = JSON.parse(metaColorsJson)
4040
41- // Read theme preference from localStorage (set by user's previous selection)
41+ /** 1. Read theme preference from localStorage (set by user's previous selection) */
4242 const stored = localStorage.getItem('theme')
4343
4444 if (stored && stored !== defaultThemeId) {
45- // User explicitly chose a theme - apply it immediately
46- // <html> element
45+ /** User explicitly chose a theme - apply it immediately */
46+ /** <html> element */
4747 document.documentElement.dataset['theme'] = stored
4848 } else if (!stored) {
49- // No stored preference - use system preference
49+ /** No stored preference - use system preference */
5050 const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
51- // <html> element
51+ /** <html> element */
5252 document.documentElement.dataset['theme'] = prefersDark ? darkThemeId : defaultThemeId
5353 }
5454
55- // 2. Turn <body> visible. It's set to hidden in BaseLayout.astro to avoid FOUC. Do
56- // here to make sure it gets turned on, in case the <meta> element selector throws.
55+ /** 2. Turn <body> visible. It's set to hidden in BaseLayout.astro to avoid FOUC. Do
56+ * here to make sure it gets turned on, in case the <meta> element selector throws.
57+ */
5758 document.body.classList.remove('invisible')
5859
59- // 3. Add theme entries from src/content/themes.json to the window.metaColors object
60+ /** 3. Add theme entries from src/content/themes.json to the window.metaColors object */
6061 window.metaColors = window.metaColors || {}
6162 Object.assign(window.metaColors, themeMetaColors)
6263
63- // 4. Update meta theme-color used for PWAs
64+ /** 4. Update meta theme-color used for PWAs */
6465 const metaElement = document.querySelector('meta[name="theme-color"]')
6566 if (stored && stored !== defaultThemeId && metaElement && window.metaColors) {
66- // User explicitly chose a theme - apply it immediately
67+ /** User explicitly chose a theme - apply it immediately */
6768 metaElement.setAttribute('content', window.metaColors[stored] || '')
6869 } else if (!stored && metaElement && window.metaColors) {
69- // No stored preference - use system preference
70+ /** No stored preference - use system preference */
7071 const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
7172 metaElement.setAttribute(
7273 'content',
7374 window.metaColors[prefersDark ? darkThemeId : defaultThemeId] || ''
7475 )
7576 }
7677
77- // 5. If stored === defaultThemeId, BaseLayout.astro already set it on <html> data-theme attribute
78- // and Meta.astro already set it on <meta name="theme-color">, so nothing to do
78+ /**
79+ * 5. If stored === defaultThemeId, BaseLayout.astro already set it
80+ * on <html> data-theme attribute and Meta.astro already set it on
81+ * <meta name="theme-color">, so nothing to do
82+ */
7983
80- // 6. Success!
84+ /** 6. Success! */
8185 console.log('🎨 Theme init on "DOMContentLoaded" executed')
8286 } catch (error) {
83- // localStorage access can fail (privacy mode, etc.)
84- // Fall back to BaseLayout's data-theme="light", make sure the page is visible
87+ /** localStorage access can fail (privacy mode, etc.) */
88+ /** Fall back to BaseLayout's data-theme="light", make sure the page is visible */
8589 document.body.classList.remove('invisible')
8690 console.error('❌ Theme init on "DOMContentLoaded" failed with errors:', error)
8791 }
8892 }, { once: true })
93+
94+ /**
95+ * Add the fast theme setting logic for Astro View Transition API navigation events.
96+ *
97+ * The DOMContentLoaded event does not fire on subsequent page transitions (soft loads).
98+ */
99+ document.addEventListener("astro:before-swap", (event) => {
100+ try {
101+ /** 1. Read theme preference from localStorage (set by user's previous selection) */
102+ const stored = localStorage.getItem('theme')
103+ /** 2. <html> element */
104+ event.newDocument.documentElement.dataset['theme'] = stored
105+ /** 3. Turn <body> visible. It's set to hidden in BaseLayout.astro to avoid FOUC */
106+ event.newDocument.body.classList.remove('invisible')
107+ /** 4. Success! */
108+ console.log('🎨 Theme init on "astro:before-swap" executed')
109+ } catch (error) {
110+ /** localStorage access can fail (privacy mode, etc.) */
111+ /** Fall back to BaseLayout's data-theme="light", make sure the page is visible */
112+ event.newDocument.body.classList.remove('invisible')
113+ console.error('❌ Theme init on "astro:before-swap" failed with errors:', error)
114+ }
115+ })
89116</script >
0 commit comments