From 624c2594f90326993b27604931b3dfd0e86bca39 Mon Sep 17 00:00:00 2001 From: David Crespo Date: Sat, 10 Oct 2026 16:39:24 +0000 Subject: [PATCH] Remeasure middle truncation when web fonts finish loading Canvas measureText uses fallback font metrics until the web font loads, and the font swap doesn't necessarily resize the container, so the ResizeObserver never fired and the truncation stayed computed against the fallback font. This made truncated UUIDs nondeterministic, which showed up as false positives in the visual regression suite. --- app/ui/lib/Truncate.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/app/ui/lib/Truncate.tsx b/app/ui/lib/Truncate.tsx index 46309a42fa..9940cd3ffd 100644 --- a/app/ui/lib/Truncate.tsx +++ b/app/ui/lib/Truncate.tsx @@ -41,7 +41,10 @@ export const Truncate = ({ const [truncated, setTruncated] = useState(false) // Middle truncation has to be computed up front in order to render at all, - // and recomputed whenever the container resizes + // and recomputed whenever the container resizes or a web font finishes + // loading. Canvas measures with fallback font metrics until the real font + // is ready, and the swap doesn't necessarily resize the container, so the + // observer alone would leave a stale truncation based on the fallback font. useLayoutEffect(() => { const el = ref.current if (position !== 'middle' || !el) return @@ -55,7 +58,11 @@ export const Truncate = ({ update() const observer = new ResizeObserver(update) observer.observe(el) - return () => observer.disconnect() + document.fonts.addEventListener('loadingdone', update) + return () => { + observer.disconnect() + document.fonts.removeEventListener('loadingdone', update) + } }, [text, position]) // For end truncation, CSS does the actual truncating and the only decision