updated the website with new features and improvements
This commit is contained in:
122
main.js
122
main.js
@@ -13,37 +13,115 @@ if (wordmark) {
|
||||
}
|
||||
|
||||
const THEME_KEY = 'theme';
|
||||
const themeToggle = document.querySelector('.theme-toggle');
|
||||
const themeMenu = document.querySelector('.theme-menu');
|
||||
const themeToggle = themeMenu ? themeMenu.querySelector('.theme-toggle') : null;
|
||||
const themeDropdown = themeMenu ? themeMenu.querySelector('.theme-dropdown') : null;
|
||||
const themeOptions = themeMenu ? themeMenu.querySelectorAll('[data-theme-choice]') : [];
|
||||
const themeQuery = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
|
||||
|
||||
function setTheme(theme) {
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
if (themeToggle) {
|
||||
themeToggle.setAttribute('aria-pressed', theme === 'dark' ? 'true' : 'false');
|
||||
themeToggle.innerHTML = theme === 'dark'
|
||||
? '<i class="fa-solid fa-sun"></i>'
|
||||
: '<i class="fa-solid fa-moon"></i>';
|
||||
function getEffectiveTheme(mode) {
|
||||
if (mode === 'auto') {
|
||||
return themeQuery && themeQuery.matches ? 'dark' : 'light';
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
function updateToggle(mode, effectiveTheme) {
|
||||
if (!themeToggle) {
|
||||
return;
|
||||
}
|
||||
|
||||
let iconClass = 'fa-circle-half-stroke';
|
||||
if (mode === 'dark') {
|
||||
iconClass = 'fa-sun';
|
||||
} else if (mode === 'light') {
|
||||
iconClass = 'fa-moon';
|
||||
}
|
||||
|
||||
themeToggle.innerHTML = `
|
||||
<i class="fa-solid ${iconClass}"></i>
|
||||
<span class="theme-caret"><i class="fa-solid fa-chevron-down"></i></span>
|
||||
`;
|
||||
themeToggle.setAttribute('aria-label', `Theme: ${mode.charAt(0).toUpperCase() + mode.slice(1)}`);
|
||||
themeToggle.setAttribute('data-effective-theme', effectiveTheme);
|
||||
}
|
||||
|
||||
function updateActiveOption(mode) {
|
||||
themeOptions.forEach((option) => {
|
||||
const isActive = option.dataset.themeChoice === mode;
|
||||
option.classList.toggle('is-active', isActive);
|
||||
option.setAttribute('aria-checked', isActive ? 'true' : 'false');
|
||||
});
|
||||
}
|
||||
|
||||
function setThemeMode(mode, persist = true) {
|
||||
const effectiveTheme = getEffectiveTheme(mode);
|
||||
document.documentElement.setAttribute('data-theme', effectiveTheme);
|
||||
updateToggle(mode, effectiveTheme);
|
||||
updateActiveOption(mode);
|
||||
if (persist) {
|
||||
localStorage.setItem(THEME_KEY, mode);
|
||||
}
|
||||
}
|
||||
|
||||
function initTheme() {
|
||||
const savedTheme = localStorage.getItem(THEME_KEY);
|
||||
if (savedTheme) {
|
||||
setTheme(savedTheme);
|
||||
return;
|
||||
}
|
||||
|
||||
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
setTheme(prefersDark ? 'dark' : 'light');
|
||||
const savedMode = localStorage.getItem(THEME_KEY);
|
||||
const mode = savedMode || 'auto';
|
||||
setThemeMode(mode, Boolean(savedMode));
|
||||
}
|
||||
|
||||
if (themeToggle) {
|
||||
function openThemeMenu() {
|
||||
if (!themeMenu || !themeToggle) {
|
||||
return;
|
||||
}
|
||||
themeMenu.classList.add('is-open');
|
||||
themeToggle.setAttribute('aria-expanded', 'true');
|
||||
}
|
||||
|
||||
function closeThemeMenu() {
|
||||
if (!themeMenu || !themeToggle) {
|
||||
return;
|
||||
}
|
||||
themeMenu.classList.remove('is-open');
|
||||
themeToggle.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
|
||||
if (themeMenu && themeToggle && themeDropdown) {
|
||||
initTheme();
|
||||
themeToggle.addEventListener('click', () => {
|
||||
const isDark = document.documentElement.getAttribute('data-theme') === 'dark';
|
||||
const nextTheme = isDark ? 'light' : 'dark';
|
||||
setTheme(nextTheme);
|
||||
localStorage.setItem(THEME_KEY, nextTheme);
|
||||
|
||||
themeToggle.addEventListener('click', (event) => {
|
||||
event.stopPropagation();
|
||||
themeMenu.classList.contains('is-open') ? closeThemeMenu() : openThemeMenu();
|
||||
});
|
||||
|
||||
themeOptions.forEach((option) => {
|
||||
option.addEventListener('click', () => {
|
||||
const mode = option.dataset.themeChoice || 'auto';
|
||||
setThemeMode(mode);
|
||||
closeThemeMenu();
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('click', (event) => {
|
||||
if (!themeMenu.contains(event.target)) {
|
||||
closeThemeMenu();
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', (event) => {
|
||||
if (event.key === 'Escape') {
|
||||
closeThemeMenu();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
initTheme();
|
||||
}
|
||||
|
||||
if (themeQuery) {
|
||||
themeQuery.addEventListener('change', () => {
|
||||
const mode = localStorage.getItem(THEME_KEY) || 'auto';
|
||||
if (mode === 'auto') {
|
||||
setThemeMode('auto', false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user