improve dashboard nav bar view

This commit is contained in:
KingKDot
2026-06-29 20:00:02 -05:00
parent 5f598aa10b
commit bf99a5dca9
3 changed files with 216 additions and 2 deletions
+113
View File
@@ -4485,6 +4485,26 @@ body.sb-open #sb-backdrop { display: block; }
justify-self: start;
min-width: 0;
}
.topbar-nav-toggle {
display: none;
align-items: center;
justify-content: center;
width: 34px;
height: 34px;
border-radius: 999px;
background: rgba(14, 165, 233, 0.12);
border: 1px solid rgba(56, 189, 248, 0.28);
color: #7dd3fc;
cursor: pointer;
flex: 0 0 auto;
transition: background 140ms ease, color 140ms ease, border-color 140ms ease;
}
.topbar-nav-toggle:hover,
.topbar-nav-toggle[aria-expanded="true"] {
background: rgba(14, 165, 233, 0.2);
color: #bae6fd;
border-color: rgba(125, 211, 252, 0.48);
}
.topbar-center {
grid-area: center;
display: flex;
@@ -4502,6 +4522,99 @@ body.sb-open #sb-backdrop { display: block; }
min-width: 0;
}
body.topbar-compact #top-nav {
position: sticky;
overflow: visible;
}
body.topbar-compact .topbar-grid {
grid-template-columns: minmax(0, 1fr) auto;
grid-template-areas: "left right";
position: relative;
}
body.topbar-compact .topbar-left {
max-width: 100%;
}
body.topbar-compact .topbar-right {
flex: 0 0 auto;
min-width: max-content;
}
body.topbar-compact .topbar-nav-toggle {
display: inline-flex;
}
body.topbar-compact .topbar-center {
position: absolute;
top: calc(100% + 10px);
left: 0;
right: 0;
display: none;
justify-self: stretch;
width: 100%;
min-width: 0;
padding: 10px;
border-radius: 10px;
background: rgba(8, 13, 28, 0.98);
border: 1px solid rgba(51, 65, 85, 0.82);
box-shadow: 0 18px 42px rgba(0, 0, 0, 0.5);
z-index: 230;
max-height: min(68vh, 520px);
overflow-y: auto;
}
body.topbar-compact.topbar-menu-open .topbar-center {
display: flex;
}
body.topbar-compact .nav-dd-bar {
justify-content: flex-start;
flex-wrap: nowrap;
align-items: stretch;
gap: 6px;
width: 100%;
padding-top: 0;
flex-direction: column;
}
body.topbar-compact .nav-dd-wrapper {
width: 100%;
}
body.topbar-compact .nav-dd-group-btn {
width: 100%;
justify-content: flex-start;
}
body.topbar-compact .nav-dd-group-btn i.fa-chevron-down {
margin-left: auto;
}
body.topbar-compact .nav-dd-menu {
position: static;
display: none;
min-width: 0;
width: 100%;
margin-top: 6px;
transform: none;
box-shadow: none;
border-radius: 8px;
background: rgba(2, 8, 22, 0.55);
border-color: rgba(51, 65, 85, 0.45);
}
body.topbar-compact .nav-dd-menu.nav-dd-open {
display: flex;
opacity: 1;
visibility: visible;
pointer-events: auto;
transform: none;
}
body.topbar-compact #account-settings-btn {
flex: 0 0 auto;
max-width: none;
min-width: max-content;
}
body.topbar-compact #username-display {
max-width: none;
overflow: visible;
text-overflow: clip;
white-space: nowrap;
}
body.topbar-compact #role-badge {
white-space: nowrap;
}
@media (max-width: 767px) {
.topbar-grid {
grid-template-columns: 1fr auto;
+99 -2
View File
@@ -165,7 +165,7 @@ function initSidebarTree(navLinks) {
────────────────────────────────────────────── */
function createTopbarController(host, refs) {
const { panel, navLinks, navUtility } = refs;
const { panel, navLinks, navUtility, topbarToggle } = refs;
if (!panel || !navLinks || !navUtility) {
return { applyAdaptiveNavLayout: () => {} };
}
@@ -175,8 +175,105 @@ function createTopbarController(host, refs) {
initDropdowns(navUtility);
initNotifyBadgeMirror(navUtility);
const grid = host.querySelector(".topbar-grid");
const left = host.querySelector(".topbar-left");
let compact = false;
let layoutFrame = 0;
const closeCompactMenu = () => {
document.body.classList.remove("topbar-menu-open");
topbarToggle?.setAttribute("aria-expanded", "false");
};
const setCompact = (next) => {
if (compact === next) return;
compact = next;
document.body.classList.toggle("topbar-compact", next);
host.dataset.navMode = next ? "compact" : "desktop";
if (!next) closeCompactMenu();
};
const measureDesktopWidth = () => {
const wasCompact = document.body.classList.contains("topbar-compact");
const wasOpen = document.body.classList.contains("topbar-menu-open");
if (wasCompact) {
document.body.classList.remove("topbar-compact", "topbar-menu-open");
}
const style = getComputedStyle(host);
const horizontalPadding = parseFloat(style.paddingLeft || "0") + parseFloat(style.paddingRight || "0");
const gridGap = grid ? parseFloat(getComputedStyle(grid).columnGap || "0") || 0 : 0;
const navGap = parseFloat(getComputedStyle(navLinks).columnGap || getComputedStyle(navLinks).gap || "0") || 0;
const visibleNavItems = Array.from(navLinks.children).filter((el) => {
const itemStyle = getComputedStyle(el);
return itemStyle.display !== "none" && !el.classList.contains("hidden");
});
const navWidth = visibleNavItems.reduce((sum, el) => sum + el.getBoundingClientRect().width, 0) +
Math.max(0, visibleNavItems.length - 1) * navGap;
const requiredWidth =
(left?.scrollWidth || 0) +
navWidth +
(navUtility?.scrollWidth || 0) +
(gridGap * 2) +
horizontalPadding +
24;
if (wasCompact) {
document.body.classList.add("topbar-compact");
document.body.classList.toggle("topbar-menu-open", wasOpen);
}
return requiredWidth;
};
const applyAdaptiveNavLayout = () => {
const availableWidth = host.clientWidth || window.innerWidth;
const requiredWidth = measureDesktopWidth();
const shouldCompact = requiredWidth > availableWidth;
setCompact(shouldCompact);
};
const scheduleAdaptiveNavLayout = () => {
if (layoutFrame) return;
layoutFrame = requestAnimationFrame(() => {
layoutFrame = 0;
applyAdaptiveNavLayout();
});
};
topbarToggle?.addEventListener("click", (event) => {
event.stopPropagation();
const nextOpen = !document.body.classList.contains("topbar-menu-open");
document.body.classList.toggle("topbar-menu-open", nextOpen);
topbarToggle.setAttribute("aria-expanded", String(nextOpen));
});
document.addEventListener("click", (event) => {
if (!compact) return;
if (event.target.closest("#top-nav")) return;
closeCompactMenu();
});
document.addEventListener("keydown", (event) => {
if (event.key === "Escape") closeCompactMenu();
});
navLinks.addEventListener("click", (event) => {
if (event.target.closest("a[href]")) closeCompactMenu();
});
window.addEventListener("resize", scheduleAdaptiveNavLayout);
if ("ResizeObserver" in window) {
const resizeObserver = new ResizeObserver(scheduleAdaptiveNavLayout);
resizeObserver.observe(host);
resizeObserver.observe(navLinks);
resizeObserver.observe(navUtility);
}
scheduleAdaptiveNavLayout();
host.dataset.navMode = "desktop";
return { applyAdaptiveNavLayout: () => {} };
return { applyAdaptiveNavLayout };
}
/* ──────────────────────────────────────────────
@@ -136,6 +136,9 @@ function mountTopbar(host) {
<a href="/" class="flex items-center gap-2 font-semibold tracking-wide">
<i class="fa-solid fa-crown header-crown"></i> Overlord
</a>
<button id="topbar-nav-toggle" class="topbar-nav-toggle" aria-label="Open navigation menu" aria-expanded="false" type="button">
<i class="fa-solid fa-layer-group"></i>
</button>
</div>
<div
id="nav-panel"
@@ -186,6 +189,7 @@ function mountTopbar(host) {
// Collect all link refs
const refs = {
toggle: null,
topbarToggle: document.getElementById("topbar-nav-toggle"),
panel: document.getElementById("nav-panel"),
collapseBtn: null,
navLinks: document.getElementById("nav-links"),