feat(nav): header unifié desktop/mobile (issue #16)

Partiel _header.html unique pour les 19 pages (fin des copies qui
dérivaient): desktop une ligne — primaires + menu Plus + Ctrl K,
page active déduite du gabarit dans render(); mobile ≤900px
burger + panneau ≥44px, Échap/clic extérieur; wallboard sans
header et triage sur le même partiel. nav.js partagé.
This commit is contained in:
Spark
2026-10-11 20:15:23 -04:00
parent 24a1ebb9a6
commit 2fde103e93
23 changed files with 204 additions and 326 deletions
+45
View File
@@ -1164,3 +1164,48 @@ footer {
.health-table th, .health-table td { text-align: left; padding: 6px 10px; border-bottom: 1px solid var(--border, #22304a); }
.health-slowest td { color: var(--warn, #e8a33d); font-weight: 600; }
.zombie-actions { display: flex; gap: 6px; flex-shrink: 0; }
/* ── Header unifié (0.15.0, #16) ── */
.main-nav { flex-wrap: nowrap; }
.header-actions { display: flex; gap: 6px; align-items: center; margin-left: auto; }
.nav-more { position: relative; }
.nav-more-btn { background: transparent; cursor: pointer; }
.nav-more-btn.active-soft { color: var(--text); border-color: var(--accent, #58a6ff); }
.nav-more-menu {
position: absolute; right: 0; top: calc(100% + 8px); z-index: 120;
min-width: 232px; display: flex; flex-direction: column; gap: 2px;
background: var(--surface-1, #131a29); border: 1px solid var(--border);
border-radius: 12px; padding: 6px;
box-shadow: 0 14px 34px rgba(0, 0, 0, 0.45);
}
.nav-more-menu .nav-pill { display: flex; border-radius: 8px; }
.nav-more-menu[hidden], .mobile-nav[hidden] { display: none !important; }
.nav-burger {
display: none; width: 40px; height: 40px; border-radius: 10px;
background: var(--surface-2); border: 1px solid var(--border);
color: var(--text); font-size: 1.05rem; cursor: pointer;
align-items: center; justify-content: center;
}
.mobile-nav {
position: absolute; top: 100%; left: 0; right: 0; z-index: 110;
display: flex; flex-direction: column; gap: 2px;
background: rgba(16, 19, 28, 0.97); backdrop-filter: blur(14px);
border-bottom: 1px solid var(--border); padding: 10px 14px 16px;
}
.mobile-nav a {
display: flex; align-items: center; min-height: 44px;
padding: 10px 12px; border-radius: 10px;
color: var(--text-2); font-size: 1rem; text-decoration: none;
}
.mobile-nav a:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }
.mobile-nav a.active {
color: #fff;
background: linear-gradient(135deg, rgba(124,92,252,.85), rgba(91,138,247,.85));
}
.crumb a { color: inherit; text-decoration: none; }
.crumb a:hover { text-decoration: underline; }
@media (max-width: 900px) {
.main-nav { display: none; }
.nav-burger { display: inline-flex; }
.crumb { display: none; }
}
+55
View File
@@ -0,0 +1,55 @@
/**
* Kanbante — header navigation (issue #16): the "Plus" dropdown on
* desktop and the burger panel on mobile. One shared partial
* (_header.html), one shared behaviour: this file.
*/
(function () {
var moreBtn = document.getElementById('nav-more-btn');
var moreMenu = document.getElementById('nav-more-menu');
var burger = document.getElementById('nav-burger');
var mobileNav = document.getElementById('mobile-nav');
function setOpen(menu, btn, open) {
if (!menu || !btn) return;
menu.hidden = !open;
btn.setAttribute('aria-expanded', open ? 'true' : 'false');
}
function closeAll() {
setOpen(moreMenu, moreBtn, false);
setOpen(mobileNav, burger, false);
if (burger) {
burger.textContent = '☰';
burger.setAttribute('aria-label', 'Ouvrir le menu');
}
}
if (moreBtn && moreMenu) {
moreBtn.addEventListener('click', function (e) {
e.stopPropagation();
var willOpen = moreMenu.hidden;
closeAll();
setOpen(moreMenu, moreBtn, willOpen);
});
moreMenu.addEventListener('click', function (e) { e.stopPropagation(); });
}
if (burger && mobileNav) {
burger.addEventListener('click', function (e) {
e.stopPropagation();
var willOpen = mobileNav.hidden;
closeAll();
setOpen(mobileNav, burger, willOpen);
burger.textContent = willOpen ? '✕' : '☰';
burger.setAttribute('aria-label', willOpen ? 'Fermer le menu' : 'Ouvrir le menu');
});
}
document.addEventListener('click', function () { closeAll(); });
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape') closeAll();
});
window.addEventListener('resize', function () {
if (window.innerWidth > 900) {
closeAll();
if (burger) burger.textContent = '☰';
}
});
})();