From 79bd56d0404439af55d7984a96bbb1b335937cb6 Mon Sep 17 00:00:00 2001 From: rcourtman Date: Thu, 25 Dec 2025 20:47:28 +0000 Subject: [PATCH] fix: URL edit popover now respects viewport boundaries. Related to #912 - Added viewport boundary detection using visualViewport API (iOS-friendly) - Popover flips above the button when there isn't enough space below - Ensures popover stays within horizontal viewport bounds --- .../src/components/shared/UrlEditPopover.tsx | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/frontend-modern/src/components/shared/UrlEditPopover.tsx b/frontend-modern/src/components/shared/UrlEditPopover.tsx index 29e8f9adf2..247fb8e813 100644 --- a/frontend-modern/src/components/shared/UrlEditPopover.tsx +++ b/frontend-modern/src/components/shared/UrlEditPopover.tsx @@ -145,12 +145,37 @@ export function createUrlEditState() { const button = event.currentTarget as HTMLElement; const rect = button.getBoundingClientRect(); - // Position below the button, slightly to the left for better visibility - setPosition({ - top: rect.bottom + 4, - left: Math.max(8, rect.left - 100) - }); + // Popover dimensions (approximate) + const popoverHeight = 80; // Approximate height of the popover + const popoverWidth = 300; // min-w-[300px] + // Get visual viewport dimensions (handles iOS Safari/Firefox address bar) + const viewportHeight = window.visualViewport?.height ?? window.innerHeight; + const viewportWidth = window.visualViewport?.width ?? window.innerWidth; + const viewportOffsetTop = window.visualViewport?.offsetTop ?? 0; + + // Check if there's enough space below the button + const spaceBelow = viewportHeight - (rect.bottom - viewportOffsetTop); + const spaceAbove = rect.top - viewportOffsetTop; + + let top: number; + if (spaceBelow >= popoverHeight + 8) { + // Position below the button + top = rect.bottom + 4; + } else if (spaceAbove >= popoverHeight + 8) { + // Flip above the button + top = rect.top - popoverHeight - 4; + } else { + // Not enough space either way, position at top of viewport with small margin + top = Math.max(8, viewportOffsetTop + 8); + } + + // Ensure left position keeps popover within viewport + let left = rect.left - 100; + left = Math.max(8, left); // Don't go off left edge + left = Math.min(left, viewportWidth - popoverWidth - 8); // Don't go off right edge + + setPosition({ top, left }); setEditingValue(currentValue); setEditingId(id); setIsEditing(true);