refactor(ui): Sidebar 1:1 an enconf-Pattern angleichen

- <aside> → <nav> als Root-Element
- Section-Label-Div NEBEN dem <ul> (vorher verschachtelt)
- <NavLink>-Callback → <Link> + location.pathname-Vergleich (Pattern
  identisch zu netcell-webpanel/management-ui/src/components/Layout/Sidebar.tsx)
- nmg-prefix CSS-Variable `--nmg-sidebar-text` entfernt, Textfarbe
  direkt #94A3B8 (enconf-Standard)

Färbung war schon enconf-konform (Gradient #0B1426→#101D33→#0D1829,
Akzent-Stab #1677ff mit color-mix tint), nur Struktur+Markup zogen
nach.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Debian
2026-05-12 14:12:26 +02:00
parent 1bb13e8107
commit 7e21fab339
6 changed files with 34 additions and 30 deletions

View File

@@ -1 +1 @@
1.0.56 1.0.57

View File

@@ -48,7 +48,7 @@ import (
wgsvc "git.netcell-it.de/projekte/edgeguard-native/internal/services/wireguard" wgsvc "git.netcell-it.de/projekte/edgeguard-native/internal/services/wireguard"
) )
var version = "1.0.56" var version = "1.0.57"
func main() { func main() {
addr := os.Getenv("EDGEGUARD_API_ADDR") addr := os.Getenv("EDGEGUARD_API_ADDR")

View File

@@ -9,7 +9,7 @@ import (
"os" "os"
) )
var version = "1.0.56" var version = "1.0.57"
const usage = `edgeguard-ctl — EdgeGuard CLI const usage = `edgeguard-ctl — EdgeGuard CLI

View File

@@ -24,7 +24,7 @@ import (
"git.netcell-it.de/projekte/edgeguard-native/internal/services/tlscerts" "git.netcell-it.de/projekte/edgeguard-native/internal/services/tlscerts"
) )
var version = "1.0.56" var version = "1.0.57"
const ( const (
// renewTickInterval — how often we re-evaluate expiring certs. // renewTickInterval — how often we re-evaluate expiring certs.

View File

@@ -1,4 +1,4 @@
import { NavLink } from 'react-router-dom' import { Link, useLocation } from 'react-router-dom'
import type { ReactNode } from 'react' import type { ReactNode } from 'react'
import { import {
ApartmentOutlined, ApartmentOutlined,
@@ -45,8 +45,6 @@ const NAV: NavSection[] = [
items: [ items: [
{ path: '/domains', labelKey: 'nav.domains', icon: <GlobalOutlined /> }, { path: '/domains', labelKey: 'nav.domains', icon: <GlobalOutlined /> },
{ path: '/backends', labelKey: 'nav.backends', icon: <DatabaseOutlined /> }, { path: '/backends', labelKey: 'nav.backends', icon: <DatabaseOutlined /> },
// /routing-rules erreichbar via Domain-Modal "Pfad-Routing"-Tab —
// kein eigener Nav-Eintrag mehr (war für 90% der Setups overkill).
], ],
}, },
{ {
@@ -77,42 +75,51 @@ const NAV: NavSection[] = [
}, },
] ]
const VERSION = '1.0.56' const VERSION = '1.0.57'
// Sidebar-Pattern 1:1 aus netcell-webpanel (enconf) übernommen:
// - <nav> als root, dunkler Gradient + Teal/Blue-Accent
// - Section-Label-Div NEBEN dem <ul>, nicht verschachtelt
// - <Link> + pathname-Vergleich für active-State (ein <li>.active::before
// rendert den Akzent-Stab links + tint die Item-Background)
// CSS lebt in styles/enterprise.css (.sidebar*).
export default function Sidebar({ isOpen, onClose }: SidebarProps) { export default function Sidebar({ isOpen, onClose }: SidebarProps) {
const { t } = useTranslation() const { t } = useTranslation()
const location = useLocation()
return ( return (
<aside className={`sidebar${isOpen ? ' open' : ''}`}> <nav className={`sidebar${isOpen ? ' open' : ''}`}>
<div className="sidebar-logo"> <div className="sidebar-logo">
<div className="sidebar-logo-icon">EG</div> <div className="sidebar-logo-icon">EG</div>
<span className="sidebar-logo-text">{t('app.title')}</span> <span className="sidebar-logo-text">{t('app.title')}</span>
</div> </div>
{NAV.map((section) => ( {NAV.map((section) => (
<div key={section.labelKey} className="sidebar-section"> <div key={section.labelKey}>
<div className="sidebar-section">
<div className="sidebar-section-label">{t(section.labelKey)}</div> <div className="sidebar-section-label">{t(section.labelKey)}</div>
</div>
<ul className="sidebar-menu"> <ul className="sidebar-menu">
{section.items.map((item) => ( {section.items.map((item) => {
<li key={item.path} className="sidebar-menu-item"> const isActive = location.pathname === item.path
<NavLink || location.pathname.startsWith(item.path + '/')
to={item.path} return (
onClick={onClose} <li
className={({ isActive }) => key={item.path}
isActive ? 'sidebar-menu-item active' : '' className={`sidebar-menu-item${isActive ? ' active' : ''}`}
}
end
> >
<Link to={item.path} onClick={onClose}>
{item.icon} {item.icon}
<span>{t(item.labelKey)}</span> <span>{t(item.labelKey)}</span>
</NavLink> </Link>
</li> </li>
))} )
})}
</ul> </ul>
</div> </div>
))} ))}
<div className="sidebar-version">v{VERSION}</div> <div className="sidebar-version">v{VERSION}</div>
</aside> </nav>
) )
} }

View File

@@ -136,10 +136,7 @@ h1, h2, h3, h4, h5, h6 {
gap: 10px; gap: 10px;
padding: 8px 10px; padding: 8px 10px;
font-size: 14px; font-size: 14px;
/* CSS-Variable --nmg-sidebar-text wird vom Sidebar-Komponente color: #94A3B8;
gesetzt wenn das Branding eine eigene Textfarbe hat. Fallback:
#94A3B8 (Light-Slate, ursprünglicher Hardcode). */
color: var(--nmg-sidebar-text, #94A3B8);
text-decoration: none; text-decoration: none;
border-radius: 6px; border-radius: 6px;
transition: all 0.15s ease; transition: all 0.15s ease;