Repository navigation
Expand file tree
/
Copy pathportfolio.js
More file actions
61 lines (59 loc) · 2.53 KB
/
Copy pathportfolio.js
File metadata and controls
61 lines (59 loc) · 2.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
(() => {
const root = document.documentElement;
const themeButton = document.getElementById('theme-toggle');
const menuButton = document.getElementById('menu-toggle');
const navigation = document.getElementById('primary-navigation');
const preference = window.matchMedia('(prefers-color-scheme: dark)');
let explicitTheme;
try { explicitTheme = localStorage.getItem('cc-theme'); } catch (_) { /* Preferences are optional. */ }
if (!['light', 'dark'].includes(explicitTheme)) explicitTheme = null;
function applyTheme(theme) {
root.dataset.theme = theme;
themeButton.textContent = theme === 'dark' ? 'Light theme' : 'Dark theme';
themeButton.setAttribute('aria-label', theme === 'dark' ? 'Switch to light theme' : 'Switch to dark theme');
}
applyTheme(explicitTheme || (preference.matches ? 'dark' : 'light'));
themeButton.hidden = false;
themeButton.addEventListener('click', () => {
explicitTheme = root.dataset.theme === 'dark' ? 'light' : 'dark';
applyTheme(explicitTheme);
try { localStorage.setItem('cc-theme', explicitTheme); } catch (_) { /* Keep the choice for this visit. */ }
});
preference.addEventListener('change', event => {
if (!explicitTheme) applyTheme(event.matches ? 'dark' : 'light');
});
function setMenu(open) {
menuButton.setAttribute('aria-expanded', String(open));
navigation.dataset.open = String(open);
}
root.dataset.enhanced = 'true';
menuButton.hidden = false;
setMenu(false);
menuButton.addEventListener('click', () => {
const open = menuButton.getAttribute('aria-expanded') !== 'true';
setMenu(open);
if (open) navigation.querySelector('a')?.focus();
});
navigation.addEventListener('click', event => {
if (event.target.closest('a')) setMenu(false);
});
document.addEventListener('keydown', event => {
if (event.key === 'Escape' && menuButton.getAttribute('aria-expanded') === 'true') {
setMenu(false);
menuButton.focus();
}
});
document.addEventListener('click', event => {
if (!navigation.contains(event.target) && !menuButton.contains(event.target)) setMenu(false);
});
function focusDestination() {
let id;
try { id = decodeURIComponent(window.location.hash.slice(1)); } catch (_) { return; }
const destination = document.getElementById(id);
if (!destination) return;
destination.setAttribute('tabindex', '-1');
destination.focus({ preventScroll: true });
}
window.addEventListener('hashchange', focusDestination);
if (window.location.hash) requestAnimationFrame(focusDestination);
})();