mirror of
https://github.com/andwati/andwati.com.git
synced 2026-10-18 17:32:52 +00:00
- new paper/ink palette with single red accent, replacing catppuccin - self-hosted IBM Plex Serif (display) + Source Serif 4 (body), drop Outfit - rebuilt homepage masthead, numbered post index, navbar with active states - switch syntax highlighting + utterances to gruvbox, synced via postMessage - remove terminal/404 easter egg chrome, clean up remaining inline styles - fix stray syntax.css link causing a 404
89 lines
3.1 KiB
JavaScript
89 lines
3.1 KiB
JavaScript
document.addEventListener('DOMContentLoaded', () => {
|
|
const themeToggleBtn = document.getElementById('theme-toggle');
|
|
const htmlElement = document.documentElement;
|
|
|
|
const applyTheme = (theme) => {
|
|
if (theme === 'dark') {
|
|
htmlElement.classList.add('dark');
|
|
} else {
|
|
htmlElement.classList.remove('dark');
|
|
}
|
|
localStorage.setItem('theme', theme);
|
|
};
|
|
|
|
// Check local storage for theme preference
|
|
const currentTheme = localStorage.getItem('theme');
|
|
if (currentTheme === 'dark' || currentTheme === 'light') {
|
|
applyTheme(currentTheme);
|
|
} else {
|
|
// Fallback to system preference
|
|
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)');
|
|
applyTheme(prefersDarkScheme.matches ? 'dark' : 'light');
|
|
}
|
|
|
|
// Toggle theme on click
|
|
if (themeToggleBtn) {
|
|
themeToggleBtn.addEventListener('click', () => {
|
|
const nextTheme = htmlElement.classList.contains('dark') ? 'light' : 'dark';
|
|
applyTheme(nextTheme);
|
|
});
|
|
}
|
|
|
|
// Mobile nav toggle
|
|
const navToggle = document.getElementById('nav-toggle');
|
|
const navLinks = document.getElementById('nav-links');
|
|
|
|
if (navToggle && navLinks) {
|
|
navToggle.addEventListener('click', () => {
|
|
const isOpen = navLinks.classList.toggle('is-open');
|
|
navToggle.setAttribute('aria-expanded', isOpen);
|
|
});
|
|
|
|
// Close nav when a link is clicked
|
|
navLinks.querySelectorAll('.nav-item').forEach((link) => {
|
|
link.addEventListener('click', () => {
|
|
navLinks.classList.remove('is-open');
|
|
navToggle.setAttribute('aria-expanded', 'false');
|
|
});
|
|
});
|
|
}
|
|
|
|
// Sync cookieconsent dark mode reactively with the site theme
|
|
const syncCCTheme = () => {
|
|
const ccMain = document.getElementById('cc-main');
|
|
if (!ccMain) return;
|
|
ccMain.classList.toggle('cc--darkmode', htmlElement.classList.contains('dark'));
|
|
};
|
|
new MutationObserver(syncCCTheme).observe(htmlElement, {
|
|
attributes: true,
|
|
attributeFilter: ['class'],
|
|
});
|
|
// Initial sync in case banner is already mounted
|
|
setTimeout(syncCCTheme, 100);
|
|
|
|
// Sync Utterances (comments iframe) theme with the site theme.
|
|
// The iframe only reads its initial `theme` attribute once, so later
|
|
// changes must go through postMessage per the utterances protocol.
|
|
const syncUtterancesTheme = () => {
|
|
const commentsEl = document.getElementById('comments');
|
|
const frame = document.querySelector('.utterances-frame');
|
|
if (!commentsEl || !frame) return;
|
|
const theme = htmlElement.classList.contains('dark')
|
|
? commentsEl.dataset.utterancesThemeDark
|
|
: commentsEl.dataset.utterancesThemeLight;
|
|
frame.contentWindow.postMessage({ type: 'set-theme', theme }, 'https://utteranc.es');
|
|
};
|
|
new MutationObserver(syncUtterancesTheme).observe(htmlElement, {
|
|
attributes: true,
|
|
attributeFilter: ['class'],
|
|
});
|
|
// The iframe loads asynchronously, so poll briefly until it's mounted.
|
|
let utterancesTries = 0;
|
|
const utterancesPoll = setInterval(() => {
|
|
if (document.querySelector('.utterances-frame') || ++utterancesTries > 20) {
|
|
clearInterval(utterancesPoll);
|
|
syncUtterancesTheme();
|
|
}
|
|
}, 250);
|
|
});
|