fix(timeline): stabilize popovers on internal scroll + expand test coverage

B-1: useViewportPopover — ignoreScrollContainers option; scroll events
originating inside the timeline canvas no longer close point-anchor popovers
B-2: AllocationPopover, DemandPopover, NewAllocationPopover — thread
scrollContainerRef through so horizontal timeline scroll is ignored
B-3: AllocationPopover — staleTime 0 so SSE reconnect triggers immediate refetch
B-4: useViewportPopover.test.ts — 6 new tests (scroll close, ignore container,
resize close, style clamping)
B-5: AllocationPopover.test.tsx — loading state + happy-path tests added

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
2026-04-02 20:49:08 +02:00
parent d4641e27aa
commit 8d9e26872b
7 changed files with 326 additions and 4 deletions
@@ -1,6 +1,6 @@
"use client";
import React from "react";
import React, { type RefObject } from "react";
import { clsx } from "clsx";
import { useEffect, useState } from "react";
import { createPortal } from "react-dom";
@@ -21,6 +21,7 @@ interface AllocationPopoverProps {
anchorX: number;
anchorY: number;
contextDate?: Date;
ignoreScrollContainers?: RefObject<HTMLElement | null>[];
}
type AllocationPopoverAssignment = Assignment<AllocationLike>;
@@ -34,6 +35,7 @@ export function AllocationPopover({
anchorX,
anchorY,
contextDate,
ignoreScrollContainers,
}: AllocationPopoverProps) {
const utils = trpc.useUtils();
const invalidateTimeline = useInvalidateTimeline();
@@ -42,13 +44,14 @@ export function AllocationPopover({
width: 300,
estimatedHeight: 360,
onClose,
...(ignoreScrollContainers ? { ignoreScrollContainers } : {}),
});
const shouldLoadAllocation = !initialAllocation;
const allocationQuery = trpc.allocation.getAssignmentById.useQuery(
{ id: allocationId },
{
staleTime: 10_000,
staleTime: 0,
enabled: shouldLoadAllocation,
retry: false,
},