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); + +