From d23a768a5fe87fcf5b78c13aaabc02f171ead564 Mon Sep 17 00:00:00 2001 From: David Langley Date: Thu, 5 Mar 2026 19:35:33 +0000 Subject: [PATCH] fix(docs): place cursor after document content is loaded, not at WASM ready --- .../views/rooms/wysiwyg_composer/DocumentView.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/web/src/components/views/rooms/wysiwyg_composer/DocumentView.tsx b/apps/web/src/components/views/rooms/wysiwyg_composer/DocumentView.tsx index ca4983d823..f5e5a1193b 100644 --- a/apps/web/src/components/views/rooms/wysiwyg_composer/DocumentView.tsx +++ b/apps/web/src/components/views/rooms/wysiwyg_composer/DocumentView.tsx @@ -480,11 +480,6 @@ export const DocumentView = memo(function DocumentView({ room }: DocumentViewPro // LiveKit real-time transport (falls back gracefully if unavailable). const rtc = useDocumentRTC(room, client); - // Place the cursor at the end and focus the editor once the WASM model is - // ready. Without this the editor is enabled but has no selection, so no - // cursor appears even after the element receives focus. - useSetCursorPosition(!isWysiwygReady, ref); - // Track whether the editor has content so we can hide the placeholder. const [hasContent, setHasContent] = useState(false); @@ -503,6 +498,13 @@ export const DocumentView = memo(function DocumentView({ room }: DocumentViewPro rtc, ); + // Place the cursor at the end and focus the editor only after BOTH the WASM + // model is ready AND the document content has been written to the DOM. + // Waiting for isLoaded prevents the cursor being placed into the empty editor + // before innerHTML is populated, which would leave it one position short on + // the first keypress. + useSetCursorPosition(!isWysiwygReady || !isLoaded, ref); + const handleInput = useCallback(() => { notifyContentChangedRef.current(); scheduleDeltaSend();