From d0b566b06dc493ffd4a748878e01e1d725ec086c Mon Sep 17 00:00:00 2001 From: Ronni Skansing Date: Thu, 14 May 2026 12:31:02 +0200 Subject: [PATCH] fix dropdown area Signed-off-by: Ronni Skansing --- .../LiveSessionBadgeDropdown.svelte | 34 ++++++------ .../table/TableDropDownEllipsis.svelte | 53 ++++++++----------- 2 files changed, 39 insertions(+), 48 deletions(-) diff --git a/frontend/src/lib/components/remote-browser/LiveSessionBadgeDropdown.svelte b/frontend/src/lib/components/remote-browser/LiveSessionBadgeDropdown.svelte index 9184206..8761a75 100644 --- a/frontend/src/lib/components/remote-browser/LiveSessionBadgeDropdown.svelte +++ b/frontend/src/lib/components/remote-browser/LiveSessionBadgeDropdown.svelte @@ -26,30 +26,32 @@ activeFormElement.set(dropdownId); const viewportHeight = window.innerHeight; + const viewportWidth = window.innerWidth; const buffer = 20; const minHeight = 64; const maxHeight = 400; + const gap = 8; - let clickViewportY, pageX, pageY; - - if (e.clientY !== undefined && e.pageX !== undefined) { - clickViewportY = e.clientY; - pageX = e.pageX; - pageY = e.pageY; + let x, y; + if (e.clientX !== undefined && e.clientY !== undefined) { + x = e.clientX; + y = e.clientY; } else { const rect = buttonRef.getBoundingClientRect(); - clickViewportY = rect.top; - pageX = rect.left + window.scrollX; - pageY = rect.top + window.scrollY; + x = rect.left + rect.width / 2; + y = rect.top; } - const spaceAbove = clickViewportY - buffer; - const spaceBelow = viewportHeight - clickViewportY - buffer; + const spaceAbove = y - buffer; + const spaceBelow = viewportHeight - y - buffer; const shouldShowAbove = spaceBelow < minHeight && spaceAbove > spaceBelow; const availableSpace = shouldShowAbove ? spaceAbove : spaceBelow; const optimalHeight = Math.min(Math.max(availableSpace, minHeight), maxHeight); - const gap = 8; - menuX = pageX - 256; + + const menuWidth = 256; + const spaceOnRight = viewportWidth - x - buffer; + menuX = spaceOnRight >= menuWidth ? x : x - menuWidth; + menuX = Math.max(buffer, Math.min(menuX, viewportWidth - menuWidth - buffer)); if (shouldShowAbove) { menuRef.style.visibility = 'hidden'; @@ -57,9 +59,9 @@ const actualMenuHeight = menuRef.scrollHeight; menuRef.style.display = ''; menuRef.style.visibility = ''; - menuY = pageY - actualMenuHeight - gap; + menuY = y - actualMenuHeight - gap; } else { - menuY = pageY + gap; + menuY = y + gap; } menuRef.style = `left: ${menuX}px; top: ${menuY}px; max-height: ${optimalHeight}px`; @@ -127,7 +129,7 @@
    diff --git a/frontend/src/lib/components/table/TableDropDownEllipsis.svelte b/frontend/src/lib/components/table/TableDropDownEllipsis.svelte index 5428dd9..f05ed5b 100644 --- a/frontend/src/lib/components/table/TableDropDownEllipsis.svelte +++ b/frontend/src/lib/components/table/TableDropDownEllipsis.svelte @@ -26,54 +26,43 @@ activeFormElement.set(dropdownId); // set this as active, closing others const viewportHeight = window.innerHeight; - const buffer = 20; // extra space to ensure some padding from viewport edges - const minHeight = 64; // minimum dropdown height - const maxHeight = 400; // maximum dropdown height + const viewportWidth = window.innerWidth; + const buffer = 20; + const minHeight = 64; + const maxHeight = 400; + const gap = 8; - let clickViewportY, pageX, pageY; - - // handle both mouse and keyboard events - if (e.clientY !== undefined && e.pageX !== undefined) { - // mouse event - clickViewportY = e.clientY; - pageX = e.pageX; - pageY = e.pageY; + // use viewport (fixed) coordinates so positioning is independent of DOM ancestors + let x, y; + if (e.clientX !== undefined && e.clientY !== undefined) { + x = e.clientX; + y = e.clientY; } else { - // keyboard event - use button position const buttonRect = buttonRef.getBoundingClientRect(); - clickViewportY = buttonRect.top; - pageX = buttonRect.left + window.scrollX; - pageY = buttonRect.top + window.scrollY; + x = buttonRect.left + buttonRect.width / 2; + y = buttonRect.top; } - // calculate available space above and below - const spaceAbove = clickViewportY - buffer; - const spaceBelow = viewportHeight - clickViewportY - buffer; - - // choose position based on available space, with preference for below + const spaceAbove = y - buffer; + const spaceBelow = viewportHeight - y - buffer; const shouldShowAbove = spaceBelow < minHeight && spaceAbove > spaceBelow; const availableSpace = shouldShowAbove ? spaceAbove : spaceBelow; - - // calculate optimal height within bounds const optimalHeight = Math.min(Math.max(availableSpace, minHeight), maxHeight); - // find position - const gap = 8; // small gap between menu and cursor/button - menuX = pageX - 256; + const menuWidth = 256; + const spaceOnRight = viewportWidth - x - buffer; + menuX = spaceOnRight >= menuWidth ? x : x - menuWidth; + menuX = Math.max(buffer, Math.min(menuX, viewportWidth - menuWidth - buffer)); if (shouldShowAbove) { - // calculate actual menu height by temporarily showing it menuRef.style.visibility = 'hidden'; menuRef.style.display = 'block'; const actualMenuHeight = menuRef.scrollHeight; menuRef.style.display = ''; menuRef.style.visibility = ''; - - // position above by moving up by the actual menu height - menuY = pageY - actualMenuHeight - gap; + menuY = y - actualMenuHeight - gap; } else { - // for below positioning, use original click/button position - menuY = pageY + gap; + menuY = y + gap; } menuRef.style = `left: ${menuX}px; top: ${menuY}px; max-height: ${optimalHeight}px`; @@ -160,7 +149,7 @@