From 853576273a4da95003a49dfc384bafd61bb70888 Mon Sep 17 00:00:00 2001 From: Sirsyorrz Date: Tue, 2 Jun 2026 01:10:52 +1000 Subject: [PATCH] Cookbook: make the GPU process popup actually visible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two bugs hid the popup that opens on double-click (or right-click) of a GPU button in the Serve panel: 1. z-index 240 vs the cookbook modal at 260 — popup rendered behind the modal it was spawned from. 2. Horizontal position was just `button.left`, with no clamp against the viewport. GPU buttons sit near the right edge of the modal, so the popup got anchored at a left that pushed most of its body past the viewport's right edge. Switch the popup to position:fixed (escapes scrolling / transform stacking contexts on any ancestor), bump z-index to 10010 (above the themed-confirm / overlay layer that sits around 9000-10000), and clamp left/top after measuring the rendered size — including flipping above the button if there isn't room below. The popup is now fully visible regardless of which GPU button it's anchored to or how narrow the viewport is. --- static/js/cookbookServe.js | 19 +++++++++++++++++-- static/style.css | 8 ++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/static/js/cookbookServe.js b/static/js/cookbookServe.js index 8ee8c5c..e353950 100644 --- a/static/js/cookbookServe.js +++ b/static/js/cookbookServe.js @@ -949,9 +949,24 @@ function _rerenderCachedModels() { document.body.appendChild(popup); panel._gpuProbe.popup = popup; + // Position below the button using viewport coords (popup is + // position:fixed). Measure the popup AFTER it's in the DOM so + // we get the real rendered size, then clamp both axes so the + // popup stays fully visible — GPU buttons near the right edge + // of the modal previously anchored the popup mostly off-screen. const r = anchorBtn.getBoundingClientRect(); - popup.style.left = `${Math.max(8, r.left)}px`; - popup.style.top = `${r.bottom + 4 + window.scrollY}px`; + const vw = window.innerWidth || document.documentElement.clientWidth; + const vh = window.innerHeight || document.documentElement.clientHeight; + const pw = popup.offsetWidth || 320; + const ph = popup.offsetHeight || 200; + let left = r.left; + let top = r.bottom + 4; + // Push left so the popup doesn't overflow the right edge. + if (left + pw > vw - 8) left = Math.max(8, vw - pw - 8); + // If there isn't room below, render above the button instead. + if (top + ph > vh - 8) top = Math.max(8, r.top - ph - 4); + popup.style.left = `${left}px`; + popup.style.top = `${top}px`; popup.querySelector('.cookbook-gpu-popup-close')?.addEventListener('click', _closeProbePopup); popup.querySelectorAll('.cookbook-gpu-kill').forEach(btn => { diff --git a/static/style.css b/static/style.css index 52c7c70..cd36f2d 100644 --- a/static/style.css +++ b/static/style.css @@ -17773,8 +17773,12 @@ body.gallery-selecting .gallery-dl-btn, .cookbook-gpu-clear:disabled { opacity: 0.4; cursor: wait; } /* GPU probe popup — per-GPU process list with kill buttons */ .cookbook-gpu-popup { - position: absolute; - z-index: 240; + /* Fixed positioning (relative to viewport) so we never get pulled into + a scrolling/transform stacking context from an ancestor. Z-index has + to clear the cookbook modal (260) and the rest of the high-z UI + layers (themed-confirm and various overlays sit around 9000-10000). */ + position: fixed; + z-index: 10010; min-width: 280px; max-width: 420px; background: var(--panel, #1a1a1a);