From 01b7f0ba44603c1073090170b6725b7e41d1fd9a Mon Sep 17 00:00:00 2001 From: Hai Shun Hsiao Date: Sun, 8 Feb 2026 18:40:27 +0000 Subject: [PATCH 1/3] fix(web): prevent context menu from overflowing viewport The context menu used `max-h-dvh` (100% viewport height) as its max height, but did not account for the menu's top position. When the menu opens at y > 0, its bottom extends beyond the viewport. Compute `maxHeight` dynamically based on the menu's top position and apply it as an inline style, so the menu always fits within the viewport and scrolls when content exceeds the available space. --- .../shared-components/context-menu/context-menu.svelte | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web/src/lib/components/shared-components/context-menu/context-menu.svelte b/web/src/lib/components/shared-components/context-menu/context-menu.svelte index 7bf9ba58b32a2..c035c2507a5ef 100644 --- a/web/src/lib/components/shared-components/context-menu/context-menu.svelte +++ b/web/src/lib/components/shared-components/context-menu/context-menu.svelte @@ -47,8 +47,9 @@ const left = Math.max(8, Math.min(window.innerWidth - rect.width, x - directionWidth)); const top = Math.max(8, Math.min(window.innerHeight - menuHeight, y)); + const maxHeight = window.innerHeight - top - 8; - return { left, top }; + return { left, top, maxHeight }; }); // We need to bind clientHeight since the bounding box may return a height @@ -78,11 +79,10 @@ aria-label={ariaLabel} aria-labelledby={ariaLabelledBy} bind:this={menuElement} - class="{isVisible - ? 'max-h-dvh' - : 'max-h-0'} flex flex-col transition-all duration-250 ease-in-out outline-none {isTransitioned + class="flex flex-col transition-all duration-250 ease-in-out outline-none {isTransitioned ? 'overflow-auto' : ''}" + style:max-height={isVisible ? `${position.maxHeight}px` : '0px'} role="menu" tabindex="-1" > From c09142286da2d6560e1fb32abca8856ffcb1f294 Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Mon, 9 Feb 2026 09:13:03 -0500 Subject: [PATCH 2/3] fix: linting --- .../shared-components/context-menu/context-menu.svelte | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/web/src/lib/components/shared-components/context-menu/context-menu.svelte b/web/src/lib/components/shared-components/context-menu/context-menu.svelte index c035c2507a5ef..92569d0422056 100644 --- a/web/src/lib/components/shared-components/context-menu/context-menu.svelte +++ b/web/src/lib/components/shared-components/context-menu/context-menu.svelte @@ -79,9 +79,7 @@ aria-label={ariaLabel} aria-labelledby={ariaLabelledBy} bind:this={menuElement} - class="flex flex-col transition-all duration-250 ease-in-out outline-none {isTransitioned - ? 'overflow-auto' - : ''}" + class="flex flex-col transition-all duration-250 ease-in-out outline-none {isTransitioned ? 'overflow-auto' : ''}" style:max-height={isVisible ? `${position.maxHeight}px` : '0px'} role="menu" tabindex="-1" From d3cff29dc0a3766ad5800faff7a1457372e8966a Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Mon, 9 Feb 2026 09:36:33 -0500 Subject: [PATCH 3/3] fix: overflow --- .../context-menu/context-menu.svelte | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/web/src/lib/components/shared-components/context-menu/context-menu.svelte b/web/src/lib/components/shared-components/context-menu/context-menu.svelte index 92569d0422056..dbe32f2701bd2 100644 --- a/web/src/lib/components/shared-components/context-menu/context-menu.svelte +++ b/web/src/lib/components/shared-components/context-menu/context-menu.svelte @@ -55,23 +55,15 @@ // We need to bind clientHeight since the bounding box may return a height // of zero when starting the 'slide' animation. let height: number = $state(0); - - let isTransitioned = $state(false);
{ - isTransitioned = true; - }} - onoutrostart={() => { - isTransitioned = false; - }} >