From 7498abb3262c07731a1bc2fd245975c29cf8bdac Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 15 Jun 2026 20:59:33 +0000 Subject: [PATCH] =?UTF-8?q?perf(cuesheet):=20revert=20lazy-autosize=20(Exp?= =?UTF-8?q?=20B)=20=E2=80=94=20metrics=20show=20it=20regresses?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Measured baseline vs lazy-autosize at CPU 4x (median of 3, ~1140 row mounts): - cell.autosize eliminated (15.2s -> 0) BUT - EventRow.mount avg +39% (179 -> 248ms), longtask +32%, longFrames 201->219, and per-row re-renders ~2x (getVisibleCells renders 4648 -> 8902). Deferring autosize destabilises virtuoso row-height measurement (rows=1 textareas), causing more re-render churn, and collapses note display. Net negative — not merged. Keeping instrumented baseline. --- .../input/auto-textarea/AutoTextarea.tsx | 43 +++++-------------- 1 file changed, 10 insertions(+), 33 deletions(-) diff --git a/apps/client/src/common/components/input/auto-textarea/AutoTextarea.tsx b/apps/client/src/common/components/input/auto-textarea/AutoTextarea.tsx index 1c52a8126..e0f91039c 100644 --- a/apps/client/src/common/components/input/auto-textarea/AutoTextarea.tsx +++ b/apps/client/src/common/components/input/auto-textarea/AutoTextarea.tsx @@ -1,6 +1,6 @@ // @ts-expect-error no types from library import autosize from 'autosize/dist/autosize'; -import { FocusEvent, RefObject, useCallback, useEffect } from 'react'; +import { RefObject, useEffect } from 'react'; import { timeSync } from '../../../devtools/cuesheet-metrics/usePerfMark'; // PERF-METRICS import Textarea, { type TextareaProps } from '../textarea/Textarea'; @@ -10,41 +10,18 @@ interface AutoTextAreaProps extends TextareaProps { } /** - * A textarea that automatically resizes based on its content. - * - * `autosize()` forces a synchronous reflow (reads scrollHeight) and installs a MutationObserver. - * Doing that on mount makes it expensive when many of these are mounted at once (e.g. virtualised - * table rows during scroll), so we only attach autosize while the field is focused for editing and - * keep it in sync with the value during that time. + * A textarea that automatically resizes based on its content */ -export function AutoTextarea({ value, inputref, onFocus, onBlur, ...textAreaProps }: AutoTextAreaProps) { - const handleFocus = useCallback( - (event: FocusEvent) => { - timeSync('cell.autosize', () => autosize(inputref.current)); // PERF-METRICS - onFocus?.(event); - }, - [inputref, onFocus], - ); - - const handleBlur = useCallback( - (event: FocusEvent) => { - if (inputref.current) { - autosize.destroy(inputref.current); - } - onBlur?.(event); - }, - [inputref, onBlur], - ); - - // while focused, keep the height in sync as the value changes +export function AutoTextarea({ value, inputref, ...textAreaProps }: AutoTextAreaProps) { + // when the value changes, we use the ref to reapply autosize useEffect(() => { const node = inputref.current; - if (node && document.activeElement === node) { - autosize(node); - } + timeSync('cell.autosize', () => autosize(inputref.current)); // PERF-METRICS + + return () => { + autosize.destroy(node); + }; }, [inputref, value]); - return ( -