diff --git a/apps/web/features/issues/components/agent-live-card.tsx b/apps/web/features/issues/components/agent-live-card.tsx index 110eb1ff..c2676724 100644 --- a/apps/web/features/issues/components/agent-live-card.tsx +++ b/apps/web/features/issues/components/agent-live-card.tsx @@ -112,8 +112,10 @@ export function AgentLiveCard({ issueId, agentName, scrollContainerRef }: AgentL const [autoScroll, setAutoScroll] = useState(true); const [cancelling, setCancelling] = useState(false); const [isStuck, setIsStuck] = useState(false); + const [cardHeight, setCardHeight] = useState(0); const scrollRef = useRef(null); const sentinelRef = useRef(null); + const cardRef = useRef(null); const seenSeqs = useRef(new Set()); // Check for active task on mount @@ -237,7 +239,13 @@ export function AgentLiveCard({ issueId, agentName, scrollContainerRef }: AgentL const observer = new IntersectionObserver( (entries) => { - if (entries[0]) setIsStuck(!entries[0].isIntersecting); + if (!entries[0]) return; + const stuck = !entries[0].isIntersecting; + // Capture expanded height before collapsing to use as placeholder + if (stuck && cardRef.current) { + setCardHeight(cardRef.current.offsetHeight); + } + setIsStuck(stuck); }, { root, threshold: 0, rootMargin: "-40px 0px 0px 0px" }, ); @@ -284,7 +292,10 @@ export function AgentLiveCard({ issueId, agentName, scrollContainerRef }: AgentL {/* Sentinel — zero-height element that IntersectionObserver watches */}
+ {/* Placeholder preserves card height when stuck, preventing layout shift */} +
+
); }