95 lines
2.8 KiB
JavaScript
95 lines
2.8 KiB
JavaScript
|
|
/**
|
||
|
|
* Theme initialization script - must run before page renders
|
||
|
|
* This prevents flash of wrong theme colors
|
||
|
|
*
|
||
|
|
* Replaces astro-themes functionality with external file to reduce HTML size
|
||
|
|
*/
|
||
|
|
(function() {
|
||
|
|
var d = document.documentElement;
|
||
|
|
var stored = localStorage.getItem('theme');
|
||
|
|
var prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||
|
|
var isDark = stored === 'dark' || (!stored && prefersDark);
|
||
|
|
var theme = isDark ? 'dark' : 'light';
|
||
|
|
|
||
|
|
// Set theme immediately
|
||
|
|
d.setAttribute('data-theme', theme);
|
||
|
|
d.style.colorScheme = theme;
|
||
|
|
if (isDark) {
|
||
|
|
d.classList.add('dark');
|
||
|
|
} else {
|
||
|
|
d.classList.remove('dark');
|
||
|
|
}
|
||
|
|
|
||
|
|
// Mark ready when DOM is ready
|
||
|
|
if (document.readyState === 'loading') {
|
||
|
|
document.addEventListener('DOMContentLoaded', function() {
|
||
|
|
d.classList.add('ready');
|
||
|
|
});
|
||
|
|
} else {
|
||
|
|
d.classList.add('ready');
|
||
|
|
}
|
||
|
|
|
||
|
|
// Handle theme changes from other tabs
|
||
|
|
window.addEventListener('storage', function(e) {
|
||
|
|
if (e.key === 'theme') {
|
||
|
|
var newTheme = e.newValue || (prefersDark ? 'dark' : 'light');
|
||
|
|
d.setAttribute('data-theme', newTheme);
|
||
|
|
d.style.colorScheme = newTheme;
|
||
|
|
if (newTheme === 'dark') {
|
||
|
|
d.classList.add('dark');
|
||
|
|
} else {
|
||
|
|
d.classList.remove('dark');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// Handle system preference changes
|
||
|
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function() {
|
||
|
|
if (!localStorage.getItem('theme')) {
|
||
|
|
var newTheme = this.matches ? 'dark' : 'light';
|
||
|
|
d.setAttribute('data-theme', newTheme);
|
||
|
|
d.style.colorScheme = newTheme;
|
||
|
|
if (newTheme === 'dark') {
|
||
|
|
d.classList.add('dark');
|
||
|
|
} else {
|
||
|
|
d.classList.remove('dark');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// Handle set-theme custom event (for toggle button)
|
||
|
|
document.addEventListener('set-theme', function(e) {
|
||
|
|
var newTheme = e.detail;
|
||
|
|
if (newTheme) {
|
||
|
|
localStorage.setItem('theme', newTheme);
|
||
|
|
} else {
|
||
|
|
localStorage.removeItem('theme');
|
||
|
|
newTheme = prefersDark ? 'dark' : 'light';
|
||
|
|
}
|
||
|
|
d.setAttribute('data-theme', newTheme);
|
||
|
|
d.style.colorScheme = newTheme;
|
||
|
|
if (newTheme === 'dark') {
|
||
|
|
d.classList.add('dark');
|
||
|
|
} else {
|
||
|
|
d.classList.remove('dark');
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// Re-apply theme after client-side navigation
|
||
|
|
// Support both original and obfuscated event names
|
||
|
|
var swapHandler = function() {
|
||
|
|
var s = localStorage.getItem('theme');
|
||
|
|
var pDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||
|
|
var t = s || (pDark ? 'dark' : 'light');
|
||
|
|
d.setAttribute('data-theme', t);
|
||
|
|
d.style.colorScheme = t;
|
||
|
|
if (t === 'dark') {
|
||
|
|
d.classList.add('dark');
|
||
|
|
} else {
|
||
|
|
d.classList.remove('dark');
|
||
|
|
}
|
||
|
|
d.classList.add('ready');
|
||
|
|
};
|
||
|
|
document.addEventListener('astro:after-swap', swapHandler);
|
||
|
|
})();
|