masonry fallback and theme toggle in, menu drawer out

This commit is contained in:
madrilene 2024-01-30 18:30:54 +01:00
parent ec3784a4a0
commit 329c7bb20a
3 changed files with 107 additions and 34 deletions

View file

@ -1,34 +0,0 @@
// © Manuel Matuzović: https://web.dev/website-navigation/
const nav = document.querySelector('nav');
const list = nav.querySelector('ul');
const burgerClone = document.querySelector('#burger-template').content.cloneNode(true);
const svg = nav.querySelector('svg');
const button = burgerClone.querySelector('button');
button.addEventListener('click', e => {
const isOpen = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', !isOpen);
});
// avoid DRY: disabling menu
const disableMenu = () => {
button.setAttribute('aria-expanded', false);
};
// close on escape
nav.addEventListener('keyup', e => {
if (e.code === 'Escape') {
disableMenu();
}
});
// close if clicked outside of event target
document.addEventListener('click', e => {
const isClickInsideElement = nav.contains(e.target);
if (!isClickInsideElement) {
disableMenu();
}
});
nav.insertBefore(burgerClone, list);

View file

@ -0,0 +1,44 @@
// ----- masonry fallback if CSS masonry not supported, solution by Ana Tudor: https://codepen.io/thebabydino/pen/yLYppjK
const supportMasonry = CSS.supports('grid-template-rows', 'masonry');
if (!supportMasonry) {
let grids = [...document.querySelectorAll('.grid[data-rows="masonry"]')];
if (grids.length && getComputedStyle(grids[0]).gridTemplateRows !== 'masonry') {
grids = grids.map(grid => ({
_el: grid,
gap: parseFloat(getComputedStyle(grid).rowGap),
items: [...grid.childNodes]
.filter(c => c.nodeType === 1 && +getComputedStyle(c).gridColumnEnd !== -1)
.map(c => ({_el: c})),
ncol: 0
}));
function layout() {
grids.forEach(grid => {
let ncol = getComputedStyle(grid._el).gridTemplateColumns.split(' ').length;
if (grid.ncol !== ncol) {
grid.ncol = ncol;
grid.items.forEach(c => c._el.style.removeProperty('margin-block-start'));
if (grid.ncol > 1) {
grid.items.slice(ncol).forEach((c, i) => {
let prev_fin = grid.items[i]._el.getBoundingClientRect().bottom,
curr_ini = c._el.getBoundingClientRect().top;
c._el.style.marginTop = `${prev_fin + grid.gap - curr_ini}px`;
});
}
}
});
}
addEventListener(
'load',
e => {
layout();
addEventListener('resize', layout, false);
},
false
);
}
}

View file

@ -0,0 +1,63 @@
const storageKey = 'theme-preference';
// get labels from meta
const lightLabel = '{{ meta.themeSwitch.light }}';
const darkLabel = '{{ meta.themeSwitch.dark }}';
const onClick = () => {
// flip current value
theme.value = theme.value === 'light' ? 'dark' : 'light';
document.querySelector('[theme-toggle]').querySelector('span').innerHTML =
theme.value === 'light' ? lightLabel : darkLabel;
setPreference();
};
const getColorPreference = () => {
if (localStorage.getItem(storageKey)) return localStorage.getItem(storageKey);
else
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
};
const setPreference = () => {
localStorage.setItem(storageKey, theme.value);
reflectPreference();
};
const reflectPreference = () => {
document.firstElementChild.setAttribute('data-theme', theme.value);
// themeToggle.querySelector('span').innerHTML =
// theme.value === 'light' ? lightLabel : darkLabel;
};
const theme = {
value: getColorPreference()
};
// set early so no page flashes / CSS is made aware
reflectPreference();
window.onload = () => {
const themeToggle = document.querySelector('[theme-toggle]');
const switcher = document.querySelector('[data-theme-switcher]');
if (!switcher) {
return;
}
switcher.removeAttribute('hidden');
reflectPreference();
themeToggle.addEventListener('click', onClick);
themeToggle.querySelector('span').innerHTML =
theme.value === 'light' ? lightLabel : darkLabel;
};
// sync with system changes
window
.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', ({matches: isDark}) => {
theme.value = isDark ? 'dark' : 'light';
setPreference();
});