mirror of
https://github.com/kernelkit/infix.git
synced 2026-08-06 07:33:01 +02:00
webui: accordion sidebar and general-purpose status badges
Replace flat nav-section-header labels with collapsible <details>/<summary> accordion groups (Network, Wireless, VPN, Services, System). Groups default open; user state persists via localStorage. Tablet icon-only mode always shows all items regardless of open/closed state. Add badge-up/down/warning/info/neutral utility classes with full dark mode support, complementing the existing firewall-specific badge variants. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
@@ -182,20 +182,50 @@ a:hover {
|
||||
}
|
||||
|
||||
.sidebar-nav {
|
||||
list-style: none;
|
||||
flex: 1;
|
||||
padding: 1rem 0;
|
||||
padding: 0.5rem 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.nav-section-header {
|
||||
/* Accordion Nav Groups */
|
||||
details.nav-group {
|
||||
border-top: 1px solid var(--sidebar-border);
|
||||
}
|
||||
details.nav-group:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
details.nav-group > summary.nav-group-summary {
|
||||
list-style: none;
|
||||
cursor: pointer;
|
||||
font-size: 0.65rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
color: var(--sidebar-fg);
|
||||
opacity: 0.5;
|
||||
padding: 1rem 1rem 0.25rem;
|
||||
pointer-events: none;
|
||||
padding: 0.875rem 1rem 0.375rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
user-select: none;
|
||||
transition: opacity 0.15s;
|
||||
}
|
||||
details.nav-group > summary.nav-group-summary:hover { opacity: 0.8; }
|
||||
details.nav-group > summary.nav-group-summary::-webkit-details-marker { display: none; }
|
||||
details.nav-group > summary.nav-group-summary::marker { display: none; }
|
||||
|
||||
details.nav-group > summary.nav-group-summary::after {
|
||||
content: '▸';
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
details[open].nav-group > summary.nav-group-summary::after {
|
||||
content: '▾';
|
||||
}
|
||||
|
||||
.nav-group-items {
|
||||
list-style: none;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.nav-icon {
|
||||
@@ -796,6 +826,31 @@ a:hover {
|
||||
.dark .badge-drop { background: var(--slate-800); color: var(--slate-400); }
|
||||
.dark .badge-continue { background: rgba(59, 130, 246, 0.2); color: #93c5fd; }
|
||||
|
||||
/* General-purpose status badges */
|
||||
.badge-up { background: #dcfce7; color: #166534; }
|
||||
.badge-down { background: #fef2f2; color: #991b1b; }
|
||||
.badge-warning { background: #fef9c3; color: #854d0e; }
|
||||
.badge-info { background: #dbeafe; color: #1e40af; }
|
||||
.badge-neutral { background: var(--slate-100); color: var(--slate-600); }
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.badge-up { background: rgba(22, 163, 74, 0.2); color: #86efac; }
|
||||
.badge-down { background: rgba(220, 38, 38, 0.2); color: #fca5a5; }
|
||||
.badge-warning { background: rgba(245, 158, 11, 0.2); color: #fcd34d; }
|
||||
.badge-info { background: rgba(59, 130, 246, 0.2); color: #93c5fd; }
|
||||
.badge-neutral { background: var(--slate-800); color: var(--slate-400); }
|
||||
}
|
||||
.dark .badge-up { background: rgba(22, 163, 74, 0.2); color: #86efac; }
|
||||
.dark .badge-down { background: rgba(220, 38, 38, 0.2); color: #fca5a5; }
|
||||
.dark .badge-warning { background: rgba(245, 158, 11, 0.2); color: #fcd34d; }
|
||||
.dark .badge-info { background: rgba(59, 130, 246, 0.2); color: #93c5fd; }
|
||||
.dark .badge-neutral { background: var(--slate-800); color: var(--slate-400); }
|
||||
.light .badge-up { background: #dcfce7; color: #166534; }
|
||||
.light .badge-down { background: #fef2f2; color: #991b1b; }
|
||||
.light .badge-warning { background: #fef9c3; color: #854d0e; }
|
||||
.light .badge-info { background: #dbeafe; color: #1e40af; }
|
||||
.light .badge-neutral { background: var(--slate-100); color: var(--slate-600); }
|
||||
|
||||
/* Interfaces */
|
||||
.iface-name { white-space: nowrap; font-weight: 500; }
|
||||
.iface-name a { color: var(--primary); text-decoration: none; }
|
||||
@@ -1047,9 +1102,13 @@ a:hover {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav-section-header {
|
||||
/* Accordion in icon-only mode: always show items, hide section headers */
|
||||
details.nav-group > summary.nav-group-summary {
|
||||
display: none;
|
||||
}
|
||||
details.nav-group:not([open]) > .nav-group-items {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
justify-content: center;
|
||||
|
||||
@@ -185,6 +185,26 @@
|
||||
});
|
||||
})();
|
||||
|
||||
// Accordion nav group persistence
|
||||
(function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.querySelectorAll('details.nav-group').forEach(function(d) {
|
||||
var label = d.querySelector('summary');
|
||||
if (!label) return;
|
||||
var key = 'nav-group:' + label.textContent.trim();
|
||||
var saved = localStorage.getItem(key);
|
||||
if (saved === 'closed') {
|
||||
d.removeAttribute('open');
|
||||
} else if (saved === 'open') {
|
||||
d.setAttribute('open', '');
|
||||
}
|
||||
d.addEventListener('toggle', function() {
|
||||
localStorage.setItem(key, d.open ? 'open' : 'closed');
|
||||
});
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
||||
// Sidebar toggle (mobile)
|
||||
(function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
Reference in New Issue
Block a user