From 5a345cd2e44399332d412e983d7d94e380e78612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hartmut=20N=C3=B6renberg?= Date: Mon, 30 Mar 2026 13:19:43 +0200 Subject: [PATCH] fix(web): portal timeline hover tooltips --- .../components/timeline/TimelineTooltip.tsx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/apps/web/src/components/timeline/TimelineTooltip.tsx b/apps/web/src/components/timeline/TimelineTooltip.tsx index 54abdce..db4aa77 100644 --- a/apps/web/src/components/timeline/TimelineTooltip.tsx +++ b/apps/web/src/components/timeline/TimelineTooltip.tsx @@ -1,5 +1,6 @@ "use client"; +import { createPortal } from "react-dom"; import { formatCents, formatDateLong } from "~/lib/format.js"; function getVacationTitle(vacation: VacationHoverData): string { @@ -78,9 +79,11 @@ export function TimelineTooltip({ demandHover, }: TimelineTooltipProps) { const vacationTitle = vacationHover ? getVacationTitle(vacationHover) : null; + const renderTooltip = (content: React.ReactNode) => + typeof document === "undefined" ? content : createPortal(content, document.body); if (demandHover && demandTooltipRef && demandTooltipPos) { - return ( + return renderTooltip(
) : null}
- + , ); } // When both are active, render a single merged tooltip using the heatmap position if (heatmapHover && vacationHover) { - return ( + return renderTooltip(
{ // Wire both refs to the same element so position updates work from either handler @@ -230,13 +233,13 @@ export function TimelineTooltip({
{vacationHover.note}
) : null}
- + , ); } // Heatmap only if (heatmapHover) { - return ( + return renderTooltip(
No bookings on this day.
)} - + , ); } // Vacation only if (vacationHover) { - return ( + return renderTooltip(
{vacationHover.note}
) : null} - + , ); }