diff --git a/.changeset/quiet-tooltips-move.md b/.changeset/quiet-tooltips-move.md new file mode 100644 index 000000000..e09bb6b4c --- /dev/null +++ b/.changeset/quiet-tooltips-move.md @@ -0,0 +1,5 @@ +--- +'@embedpdf/snippet': patch +--- + +Guard tooltip positioning when the tooltip unmounts before Floating UI resolves. diff --git a/viewers/snippet/src/components/ui/tooltip.tsx b/viewers/snippet/src/components/ui/tooltip.tsx index 97d179365..609393157 100644 --- a/viewers/snippet/src/components/ui/tooltip.tsx +++ b/viewers/snippet/src/components/ui/tooltip.tsx @@ -49,23 +49,31 @@ export function Tooltip({ if (!reference.current?.base || !floating.current) return; return autoUpdate(reference.current.base, floating.current, () => { - computePosition(reference.current!.base, floating.current!, { + const referenceEl = reference.current?.base; + const floatingEl = floating.current; + const arrowEl = arrow.current; + + if (!referenceEl || !floatingEl || !arrowEl) return; + + computePosition(referenceEl, floatingEl, { placement: position, middleware: [ offset(8), flip(), shift({ padding: 8 }), - arrowMw({ element: arrow.current!, padding: 6 }), + arrowMw({ element: arrowEl, padding: 6 }), ], }).then(({ x, y, placement, middlewareData }) => { - Object.assign(floating.current!.style, { left: `${x}px`, top: `${y}px` }); + if (!floating.current || !arrow.current) return; + + Object.assign(floating.current.style, { left: `${x}px`, top: `${y}px` }); const { x: ax, y: ay } = middlewareData.arrow ?? {}; const side = placement.split('-')[0] as 'top' | 'bottom' | 'left' | 'right'; const staticSide = { top: 'bottom', bottom: 'top', left: 'right', right: 'left' }[side]; /* --- **critical change**: clear the axis we don't use --- */ - Object.assign(arrow.current!.style, { + Object.assign(arrow.current.style, { left: ax != null ? `${ax}px` : '', top: ay != null ? `${ay}px` : '', right: '',