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:
@@ -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 ═══ -->
|
||||||
|
|||||||
Reference in New Issue
Block a user