105 lines
4.5 KiB
JavaScript
105 lines
4.5 KiB
JavaScript
/**
|
|
* Kanbante — sidebar behaviour (issue #16, 0.16.0 layout).
|
|
* Desktop: collapse to an icon rail (persisted in localStorage).
|
|
* Mobile: the same sidebar becomes an off-canvas drawer, toggled
|
|
* by the topbar burger, closed by backdrop / Escape / navigation.
|
|
*/
|
|
(function () {
|
|
var burger = document.getElementById('nav-burger');
|
|
var backdrop = document.getElementById('side-backdrop');
|
|
var collapseBtn = document.getElementById('side-collapse');
|
|
|
|
function closeDrawer() {
|
|
document.body.classList.remove('sidebar-open');
|
|
if (backdrop) backdrop.hidden = true;
|
|
if (burger) {
|
|
burger.setAttribute('aria-expanded', 'false');
|
|
burger.textContent = '☰';
|
|
}
|
|
}
|
|
|
|
if (burger) {
|
|
burger.addEventListener('click', function () {
|
|
var open = document.body.classList.toggle('sidebar-open');
|
|
burger.setAttribute('aria-expanded', open ? 'true' : 'false');
|
|
burger.textContent = open ? '✕' : '☰';
|
|
if (backdrop) backdrop.hidden = !open;
|
|
});
|
|
}
|
|
if (backdrop) backdrop.addEventListener('click', closeDrawer);
|
|
document.addEventListener('keydown', function (e) {
|
|
if (e.key === 'Escape') closeDrawer();
|
|
});
|
|
window.addEventListener('resize', function () {
|
|
if (window.innerWidth > 900) closeDrawer();
|
|
});
|
|
|
|
/* Bascule Dark/Light (#52) : le choix est mémorisé et
|
|
l'amorce de _header.html l'a déjà appliqué avant le rendu.
|
|
Ici, on ne fait que synchroniser le libellé et le clic. */
|
|
var themeBtn = document.getElementById('theme-toggle');
|
|
function syncThemeBtn(theme) {
|
|
if (!themeBtn) return;
|
|
var light = theme === 'light';
|
|
/* Bouton dans la section Administration (#55) : icône et
|
|
libellé sont des <span> séparés ; l'ancien bouton de
|
|
l'en-tête, lui, n'avait qu'un texte. */
|
|
var ico = themeBtn.querySelector('[data-theme-ico]');
|
|
var lbl = themeBtn.querySelector('[data-theme-label]');
|
|
if (ico) ico.textContent = light ? '🌙' : '☀️';
|
|
if (lbl) lbl.textContent = light ? 'Mode sombre' : 'Mode clair';
|
|
if (!ico && !lbl) {
|
|
themeBtn.textContent = light ? '🌙 Mode sombre' : '☀️ Mode clair';
|
|
}
|
|
themeBtn.setAttribute('aria-pressed', light ? 'true' : 'false');
|
|
}
|
|
if (themeBtn) {
|
|
syncThemeBtn(document.documentElement.getAttribute('data-theme') || 'dark');
|
|
themeBtn.addEventListener('click', function () {
|
|
var next = document.documentElement.getAttribute('data-theme') === 'light' ? 'dark' : 'light';
|
|
document.documentElement.setAttribute('data-theme', next);
|
|
try { localStorage.setItem('kanbante-theme', next); } catch (e) { /* non-fatal */ }
|
|
syncThemeBtn(next);
|
|
});
|
|
}
|
|
|
|
if (collapseBtn) {
|
|
collapseBtn.addEventListener('click', function () {
|
|
var collapsed = document.body.classList.toggle('sidebar-collapsed');
|
|
try {
|
|
localStorage.setItem('kanbante-sidebar', collapsed ? 'collapsed' : 'open');
|
|
} catch (e) { /* private mode: state lasts for the page only */ }
|
|
});
|
|
}
|
|
|
|
/* Accordéon EXCLUSIF (0.22.0) : une seule section ouverte
|
|
à la fois. Ouvrir une section ferme les autres ; cliquer
|
|
la section ouverte la referme. L'état initial vient du
|
|
script d'amorce de _header.html (section de la page
|
|
courante ou choix mémorisé dans kanbante-nav-open). */
|
|
var groupBtns = document.querySelectorAll('[data-group-btn]');
|
|
function syncGroupBtn(btn) {
|
|
var closed = document.body.classList.contains(
|
|
'nav-closed-' + btn.getAttribute('data-group-btn'));
|
|
btn.setAttribute('aria-expanded', closed ? 'false' : 'true');
|
|
}
|
|
function setOpenGroup(openKey) {
|
|
groupBtns.forEach(function (btn) {
|
|
var key = btn.getAttribute('data-group-btn');
|
|
document.body.classList.toggle('nav-closed-' + key, key !== openKey);
|
|
syncGroupBtn(btn);
|
|
});
|
|
try {
|
|
localStorage.setItem('kanbante-nav-open', openKey);
|
|
} catch (e) { /* non-fatal */ }
|
|
}
|
|
groupBtns.forEach(function (btn) {
|
|
syncGroupBtn(btn);
|
|
btn.addEventListener('click', function () {
|
|
var key = btn.getAttribute('data-group-btn');
|
|
var isOpen = !document.body.classList.contains('nav-closed-' + key);
|
|
setOpenGroup(isOpen ? '' : key);
|
|
});
|
|
});
|
|
})();
|