updated the website with new features and improvements

This commit is contained in:
2026-02-12 17:28:25 -05:00
parent b26ebb6d6e
commit 36f7d0ed8b
5 changed files with 383 additions and 39 deletions

122
main.js
View File

@@ -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);
}
});
}