(() => {
const STORAGE_KEY = 'colorMode';
const DEFAULT_MODE = 'system';
const supportedModes = ['light', 'dark', 'system'];
const iconMarkup = {
system: '',
light: '',
dark: ''
};
const getStoredMode = () => localStorage.getItem(STORAGE_KEY);
const getPreferredTheme = () => window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
const normalizeMode = (mode) => supportedModes.includes(mode) ? mode : DEFAULT_MODE;
const setMode = (mode, persist = true) => {
const normalizedMode = normalizeMode(mode);
if (persist) {
localStorage.setItem(STORAGE_KEY, normalizedMode);
}
applyTheme(normalizedMode);
updateMenuState(normalizedMode);
};
const applyTheme = (mode) => {
const theme = mode === 'system' ? getPreferredTheme() : mode;
document.documentElement.dataset.bsTheme = theme;
document.body.classList.remove('theme-light', 'theme-dark');
document.body.classList.add(`theme-${theme}`);
};
const updateMenuState = (mode) => {
const iconContainer = document.getElementById('color-mode-icon');
const label = document.getElementById('color-mode-label');
const menuItems = document.querySelectorAll('[data-color-mode]');
if (iconContainer) {
iconContainer.innerHTML = iconMarkup[mode] ?? iconMarkup.system;
}
if (label) {
label.textContent = mode.charAt(0).toUpperCase() + mode.slice(1);
}
menuItems.forEach((item) => {
const itemMode = item.dataset.colorMode;
item.classList.toggle('active', itemMode === mode);
});
};
const bindMenuActions = () => {
document.querySelectorAll('[data-color-mode]').forEach((item) => {
item.addEventListener('click', () => setMode(item.dataset.colorMode, true));
});
};
const initialMode = normalizeMode(getStoredMode() ?? DEFAULT_MODE);
applyTheme(initialMode);
updateMenuState(initialMode);
bindMenuActions();
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
const storedMode = normalizeMode(getStoredMode() ?? DEFAULT_MODE);
if (storedMode === 'system') {
applyTheme(event.matches ? 'dark' : 'light');
}
});
})();