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 dbe32f2701..58ae508320 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
@@ -2,8 +2,6 @@
import { clickOutside } from '$lib/actions/click-outside';
import { languageManager } from '$lib/managers/language-manager.svelte';
import type { Snippet } from 'svelte';
- import { quintOut } from 'svelte/easing';
- import { slide } from 'svelte/transition';
interface Props {
isVisible?: boolean;
@@ -14,6 +12,7 @@
ariaLabel?: string | undefined;
ariaLabelledBy?: string | undefined;
ariaActiveDescendant?: string | undefined;
+ menuScrollView?: HTMLDivElement | undefined;
menuElement?: HTMLUListElement | undefined;
onClose?: (() => void) | undefined;
children?: Snippet;
@@ -28,6 +27,7 @@
ariaLabel = undefined,
ariaLabelledBy = undefined,
ariaActiveDescendant = undefined,
+ menuScrollView = $bindable(),
menuElement = $bindable(),
onClose = undefined,
children,
@@ -37,33 +37,43 @@
const layoutDirection = $derived(languageManager.rtl ? swap(direction) : direction);
const position = $derived.by(() => {
- if (!menuElement) {
+ if (!menuScrollView || !menuElement) {
return { left: 0, top: 0 };
}
- const rect = menuElement.getBoundingClientRect();
+ const rect = menuScrollView.getBoundingClientRect();
const directionWidth = layoutDirection === 'left' ? rect.width : 0;
- const menuHeight = Math.min(menuElement.clientHeight, height) || 0;
- 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;
+ const margin = 8;
- return { left, top, maxHeight };
+ const left = Math.max(margin, Math.min(windowInnerWidth - rect.width - margin, x - directionWidth));
+ const top = Math.max(margin, Math.min(windowInnerHeight - menuElement.clientHeight, y));
+ const maxHeight = windowInnerHeight - top - margin;
+
+ const needScrollBar = menuElement.clientHeight > maxHeight;
+
+ return { left, top, maxHeight, needScrollBar };
});
- // 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 windowInnerHeight: number = $state(0);
+ let windowInnerWidth: number = $state(0);
+