From cbf0e4aa51f7f1a2117c21e13ff266165af29645 Mon Sep 17 00:00:00 2001 From: Peter Meier Date: Sat, 16 May 2026 15:22:27 +0200 Subject: [PATCH] =?UTF-8?q?Fix=20Tooltip=20clipping=20in=20overflow-hidden?= =?UTF-8?q?=20containers=20=E2=80=94=20use=20fixed=20positioning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switches from absolute (clipped by ancestor overflow:hidden) to fixed with viewport-relative coords from getBoundingClientRect(). Co-Authored-By: Claude Sonnet 4.6 --- src/lib/ui/Tooltip.svelte | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/src/lib/ui/Tooltip.svelte b/src/lib/ui/Tooltip.svelte index c1e38c4..4edb555 100644 --- a/src/lib/ui/Tooltip.svelte +++ b/src/lib/ui/Tooltip.svelte @@ -13,7 +13,8 @@ let wrapperEl = $state(null); let showTooltip = $state(false); let placement = $state<"top" | "bottom">("top"); - let leftPx = $state(null); // null = centered (CSS), number = clamped px from wrapper left + let fixedLeft = $state(0); + let fixedTop = $state(0); function updatePosition() { if (!wrapperEl) return; @@ -25,20 +26,13 @@ const spaceBelow = vh - rect.bottom; placement = preferredPlacement === "top" - ? spaceAbove >= spaceBelow - ? "top" - : "bottom" - : spaceBelow >= spaceAbove - ? "bottom" - : "top"; + ? spaceAbove >= spaceBelow ? "top" : "bottom" + : spaceBelow >= spaceAbove ? "bottom" : "top"; const iconCenterX = rect.left + rect.width / 2; const idealLeft = iconCenterX - TOOLTIP_MAX_WIDTH_PX / 2; - const clampedLeft = Math.max( - TOOLTIP_GAP, - Math.min(idealLeft, vw - TOOLTIP_MAX_WIDTH_PX - TOOLTIP_GAP), - ); - leftPx = clampedLeft - rect.left; + fixedLeft = Math.max(TOOLTIP_GAP, Math.min(idealLeft, vw - TOOLTIP_MAX_WIDTH_PX - TOOLTIP_GAP)); + fixedTop = placement === "top" ? rect.top - TOOLTIP_GAP : rect.bottom + TOOLTIP_GAP; } function handleShow() { @@ -48,16 +42,12 @@ function handleHide() { showTooltip = false; - leftPx = null; } - const placementClasses = $derived( + const tooltipStyle = $derived( placement === "top" - ? "bottom-full mb-2" - : "top-full mt-2", - ); - const horizontalStyle = $derived( - leftPx != null ? `left: ${leftPx}px; transform: none;` : "left: 50%; transform: translateX(-50%);", + ? `position:fixed;top:${fixedTop}px;left:${fixedLeft}px;transform:translateY(-100%);` + : `position:fixed;top:${fixedTop}px;left:${fixedLeft}px;`, ); @@ -74,8 +64,8 @@ {#if showTooltip}