responsive nav: hamburger menu <=1100px, column buttons <=640px, endpoint pill ellipsis, injected buttons (Export/Update/Topology) relocate into the menu

This commit is contained in:
Hermes
2026-10-01 21:45:17 +00:00
parent 212d04f87d
commit 43e5d0b7d8

View File

@@ -14,6 +14,28 @@
<link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="styles_v2.css"> <link rel="stylesheet" href="styles_v2.css">
<style>
/* ── responsive nav (2026-09-30) ── */
.hamburger-btn { display: none; background: rgba(15,23,42,0.8); border: 1px solid var(--border-color);
color: #e2e8f0; border-radius: 8px; padding: 0.55rem 0.8rem; font-size: 1.1rem; cursor: pointer; }
@media (max-width: 1100px) {
.top-nav { flex-wrap: wrap; gap: 0.5rem; }
.nav-metrics { order: 3; width: 100%; justify-content: flex-start; gap: 0.5rem; }
.metric-pill { font-size: 0.7rem; padding: 0.25rem 0.5rem; max-width: 48%; overflow: hidden; }
.metric-pill .pill-value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: inline-block; max-width: 180px; vertical-align: bottom; }
.hamburger-btn { display: inline-block; order: 2; margin-left: auto; }
.nav-menu { display: none; order: 4; width: 100%; }
.nav-menu.open { display: block; }
.nav-menu .action-area { display: flex !important; flex-wrap: wrap; gap: 0.4rem !important; padding: 0.5rem 0;
border-top: 1px solid var(--border-color); }
.nav-menu .btn { padding: 0.4rem 0.6rem; font-size: 0.75rem; }
.action-area .btn i { margin-right: 0.25rem; }
}
@media (max-width: 640px) {
.nav-menu .action-area { flex-direction: column; }
.nav-menu .btn { width: 100%; text-align: left; }
}
</style>
</head> </head>
<body> <body>
@@ -41,7 +63,11 @@
</div> </div>
</div> </div>
<div class="action-area" style="display: flex; gap: 0.75rem;"> <button id="hamburgerBtn" class="hamburger-btn" onclick="toggleNavMenu()" aria-label="Menu">
<i class="fa-solid fa-bars"></i>
</button>
<div id="navMenu" class="nav-menu">
<div class="action-area" style="display: flex; gap: 0.75rem; flex-wrap: wrap;">
<a href="/api/export/csv" class="btn btn-secondary" style="text-decoration: none;" download> <a href="/api/export/csv" class="btn btn-secondary" style="text-decoration: none;" download>
<i class="fa-solid fa-file-csv"></i> Nodes CSV <i class="fa-solid fa-file-csv"></i> Nodes CSV
</a> </a>
@@ -67,6 +93,7 @@
<i class="fa-solid fa-skull"></i> Kill Switch <i class="fa-solid fa-skull"></i> Kill Switch
</button> </button>
</div> </div>
</div>
</header> </header>
<!-- Main Container --> <!-- Main Container -->
@@ -602,6 +629,30 @@ function applyInstallerPersist() {
} }
document.addEventListener('DOMContentLoaded', () => setTimeout(applyInstallerPersist, 100)); document.addEventListener('DOMContentLoaded', () => setTimeout(applyInstallerPersist, 100));
</script> </script>
<script>
function toggleNavMenu() {
const m = document.getElementById('navMenu');
const b = document.getElementById('hamburgerBtn');
if (m && b) {
m.classList.toggle('open');
b.innerHTML = m.classList.contains('open') ? '<i class="fa-solid fa-xmark"></i>' : '<i class="fa-solid fa-bars"></i>';
}
}
// injected buttons (Export All, Update All, Topology) go into the nav-menu when it exists
const _origNavInject = setInterval(() => {
const menu = document.getElementById('navMenu');
if (!menu) return;
clearInterval(_origNavInject);
const mo = new MutationObserver(() => {
const ks = document.querySelector('.nav-menu button[onclick="killSwitch()"]');
['exportAllBtn', 'updateAllBtn', 'topoBtn'].forEach(id => {
const b = document.getElementById(id);
if (b && !menu.contains(b)) menu.querySelector('.action-area').appendChild(b);
});
});
mo.observe(document.body, { childList: true, subtree: true });
}, 500);
</script>
</body> </body>
</html> </html>
<!-- ═══ NexusOps v2 UI markup ═══ --> <!-- ═══ NexusOps v2 UI markup ═══ -->