[eric] chat: the frozen shot and the live mini never paint together, the misaligned double-page overlap dies

This commit is contained in:
ciregenz
2026-08-04 20:51:47 -07:00
parent 8d014db030
commit b722dbd2f8
2 changed files with 18 additions and 0 deletions
@@ -283,6 +283,8 @@ const AgentChat: React.FC<AgentChatProps> = ({ sessionId: sessionIdProp, onClose
borderRadius: '12px',
overflow: 'hidden',
border: `1px solid ${c.border.medium}`,
// The live overlay stamps data-mini-live; while it paints, the frozen-shot backdrop must not (the clamped overlay leaves margins where a misaligned second copy of the page peeked through).
'&[data-mini-live="1"] img': { opacity: 0 },
} as const;
// A live webview cannot be clipped by the scroller, so the OVERLAY only shows while fully in view; this frozen shot is what scrolls and clips underneath it, ChatGPT-style.
const dockedShot = dockedSurfaceId ? getMinimizedShot(dockedSurfaceId) : undefined;
@@ -318,6 +318,22 @@ const BrowserCard: React.FC<Props> = ({
}, [dockedTo, dockParentExpanded, dockParentTiled, dockParentCard?.x, dockParentCard?.y, dockParentCard?.width, dockParentCard?.height, getCanvasState, dockParentCard]);
const dockParentZ = dockParentCard?.zOrder ?? 0;
// The slot's frozen-shot backdrop and the live overlay must never BOTH paint (the clamped overlay leaves margins where a misaligned copy of the page peeks through), so the card stamps its live state onto the slot and the slot's CSS hides the shot while live.
const overlayLiveRef = useRef(false);
useEffect(() => {
if (!dockedTo) return undefined;
const stamp = (): void => {
const slot = document.querySelector(`[data-browser-slot="${dockedTo}"]`);
slot?.setAttribute('data-mini-live', overlayLiveRef.current ? '1' : '0');
};
stamp();
const t = window.setInterval(stamp, 400);
return () => {
window.clearInterval(t);
document.querySelector(`[data-browser-slot="${dockedTo}"]`)?.setAttribute('data-mini-live', '0');
};
}, [dockedTo]);
// The chat drags on a per-frame compositor transform, but dock geometry only re-measures at settle; ride the same drag channel imperatively or the mini visibly trails its own chat.
const hasDockRect = !!dockRect;
useEffect(() => {