From 5d674fe61b90b76b0db685ff103113f321deb8c6 Mon Sep 17 00:00:00 2001 From: Lukas Parsons Date: Tue, 7 Jul 2026 15:12:59 -0400 Subject: [PATCH] fix: zoom-aware dropdown positioning in session list + archive/research menus getBoundingClientRect() returns zoom-scaled coords, but window.innerWidth is unscaled. rect.right/z computed offset was wildly negative at ui-scale-125, pushing dropdowns off-screen left. Both createSessionItem() dropdown (rename/delete/archive) and _showDropdown() (archive/research library cards) affected. --- static/js/sessions.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/static/js/sessions.js b/static/js/sessions.js index fb13af3b..9ba9178b 100644 --- a/static/js/sessions.js +++ b/static/js/sessions.js @@ -825,17 +825,18 @@ function createSessionItem(s) { } else { // Position the dropdown using viewport coords const rect = menuBtn.getBoundingClientRect(); + const z = parseFloat(getComputedStyle(document.documentElement).zoom) || 1; dropdown.style.left = ''; - dropdown.style.right = (window.innerWidth - rect.right) + 'px'; + dropdown.style.right = (window.innerWidth - rect.right / z) + 'px'; // Show off-screen first to measure height dropdown.style.top = '-9999px'; dropdown.style.display = 'block'; const ddRect = dropdown.getBoundingClientRect(); // Flip above if not enough room below - if (rect.bottom + 2 + ddRect.height > window.innerHeight) { - dropdown.style.top = Math.max(2, rect.top - ddRect.height - 2) + 'px'; + if (rect.bottom / z + 2 + ddRect.height / z > window.innerHeight) { + dropdown.style.top = Math.max(2, rect.top / z - ddRect.height / z - 2) + 'px'; } else { - dropdown.style.top = rect.bottom + 2 + 'px'; + dropdown.style.top = rect.bottom / z + 2 + 'px'; } } }); @@ -2669,14 +2670,15 @@ function _showDropdown(anchorEl, items) { // Position using viewport coords (same pattern as session menus) const rect = anchorEl.getBoundingClientRect(); - dd.style.right = (window.innerWidth - rect.right) + 'px'; + const z = parseFloat(getComputedStyle(document.documentElement).zoom) || 1; + dd.style.right = (window.innerWidth - rect.right / z) + 'px'; dd.style.top = '-9999px'; dd.style.display = 'block'; const ddRect = dd.getBoundingClientRect(); - if (rect.bottom + 2 + ddRect.height > window.innerHeight) { - dd.style.top = Math.max(2, rect.top - ddRect.height - 2) + 'px'; + if (rect.bottom / z + 2 + ddRect.height / z > window.innerHeight) { + dd.style.top = Math.max(2, rect.top / z - ddRect.height / z - 2) + 'px'; } else { - dd.style.top = (rect.bottom + 2) + 'px'; + dd.style.top = (rect.bottom / z + 2) + 'px'; } function close() { dd.remove(); }