mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-06-04 07:51:20 +00:00
fix(nav): .nav-more-wrap contain:layout — open dropdown inflated parent flex line, clipped nav offscreen (#1406)
ACTUAL root cause of the recurring nav-vanishing bug, validated live via Chrome CDP probe on staging at vw=1030. ## What happens When the More dropdown opens: - BEFORE: nav_links.y = 2.67, nav_left.scrollHeight = 47, nav visible ✅ - OPEN: nav_links.y = -46.67, nav_left.scrollHeight = 279, nav clipped offscreen ❌ The .nav-more-menu is position:absolute but its content extents inflate .nav-more-wrap.scrollHeight. .nav-left { display:flex; align-items:center } then centers a 279px content line in a 52px container, putting everything above the visible band. ## Fix Add contain:layout to .nav-more-wrap — isolates its layout box from the parent flex calculation. No more bubble-up. CDP verification with the fix applied: dropdown opens, all 6 items render at proper y (56, 93, 130, 166, 203, 240), nav_links_y stays at 2.67, nav_left.scrollHeight stays at 47. ## Why prior 22 fixes didn't catch it Every prior fix treated symptoms — Priority+ algorithm tweaks, overflow flag toggles, min-height drops, etc. None instrumented the CLOSED→OPEN state transition that reveals the flex-line bug. Required Chrome DevTools Protocol on a real broken viewport to see the inflate happen live. Fixes #1406 and likely supersedes #1391, #1396, #1400, #1404. Co-authored-by: openclaw-bot <bot@openclaw.local>
This commit is contained in:
@@ -1348,9 +1348,19 @@ window.addEventListener('DOMContentLoaded', () => {
|
||||
requestAnimationFrame(applyNavPriority);
|
||||
});
|
||||
|
||||
// #1406: position the fixed dropdown relative to the More button on each open.
|
||||
// Required because .nav-more-menu is position:fixed (so it escapes
|
||||
// .nav-more-wrap's layout box and doesn't inflate the parent flex line).
|
||||
function positionMoreMenu() {
|
||||
var wr = navMoreWrap.getBoundingClientRect();
|
||||
navMoreMenu.style.top = (wr.bottom + 4) + 'px';
|
||||
navMoreMenu.style.right = (window.innerWidth - wr.right) + 'px';
|
||||
navMoreMenu.style.left = 'auto';
|
||||
}
|
||||
navMoreBtn.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
const opening = !navMoreMenu.classList.contains('open');
|
||||
if (opening) positionMoreMenu();
|
||||
navMoreMenu.classList.toggle('open');
|
||||
navMoreBtn.setAttribute('aria-expanded', String(opening));
|
||||
if (opening) {
|
||||
@@ -1358,6 +1368,10 @@ window.addEventListener('DOMContentLoaded', () => {
|
||||
if (firstLink) firstLink.focus();
|
||||
}
|
||||
});
|
||||
// Re-position on window resize while open.
|
||||
window.addEventListener('resize', () => {
|
||||
if (navMoreMenu.classList.contains('open')) positionMoreMenu();
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', (e) => {
|
||||
|
||||
+7
-1
@@ -1691,8 +1691,14 @@ button.ch-item:hover .ch-icon-btn { opacity: 1; }
|
||||
/* "More" button (hidden on desktop) */
|
||||
.nav-more-wrap { display: none; position: relative; }
|
||||
.nav-more-btn { display: inline-flex; }
|
||||
/* #1406: position:fixed (not absolute) so the dropdown escapes .nav-more-wrap's
|
||||
layout box. When absolute, the dropdown's content extents inflated
|
||||
.nav-more-wrap.scrollHeight → bubbled into .nav-left flex line-height calc
|
||||
→ centered a 279px content line in 52px container → entire nav strip clipped
|
||||
above viewport. position:fixed removes the dropdown from flow entirely; JS in
|
||||
app.js positions top/right dynamically relative to the More button. */
|
||||
.nav-more-menu {
|
||||
display: none; position: absolute; top: calc(var(--top-nav-h, 52px) - 4px); right: 0;
|
||||
display: none; position: fixed; right: 0; top: 0;
|
||||
background: var(--nav-bg); border: 1px solid var(--border); border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.15); flex-direction: column;
|
||||
min-width: 160px; padding: 4px 0; z-index: 1200;
|
||||
|
||||
Reference in New Issue
Block a user