From 767736ff1e43250786feffc366c6b86aeeec3370 Mon Sep 17 00:00:00 2001 From: emozilla Date: Sun, 10 May 2026 01:43:52 -0400 Subject: [PATCH] fix(desktop): keep composer contenteditable mounted across stacked toggle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The composer rendered {input} inside two different parent fragments depending on `stacked`. When auto-expand flipped `stacked` (e.g. the moment typed text wrapped past two lines), React reconciled the two branches as different positions and unmounted/remounted the contenteditable. The fresh mount started empty, so any in-flight characters — most reliably reproduced by holding a key — were lost. Replace the conditional with a single CSS Grid whose template-areas swap on `stacked`. The three children (menu, input, controls) keep stable identities across the toggle; only their grid placement changes, which the browser handles without React tearing down the editor. --- apps/desktop/src/app/chat/composer/index.tsx | 39 ++++++++++++-------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/apps/desktop/src/app/chat/composer/index.tsx b/apps/desktop/src/app/chat/composer/index.tsx index 21034f68af..e13df39b7b 100644 --- a/apps/desktop/src/app/chat/composer/index.tsx +++ b/apps/desktop/src/app/chat/composer/index.tsx @@ -1006,21 +1006,30 @@ export function ChatBar({ {attachments.length > 0 && } - {stacked ? ( - <> - {input} -
- {contextMenu} - {controls} -
- - ) : ( -
- {contextMenu} - {input} - {controls} -
- )} + {/* + Single CSS Grid keeps {input} (and the contenteditable inside + it) in a stable parent across the stacked/inline toggle. + Earlier this was a JSX conditional that rendered {input} + inside two different fragments — when `stacked` flipped (e.g. + the moment text wrapped past two lines and the auto-expand + effect triggered), React reconciled them as different + positions and unmounted/remounted the contenteditable. The + fresh mount started empty and any in-flight characters were + lost. Switching the layout via grid-template-areas keeps the + exact same DOM nodes and lets the browser handle the reflow. + */} +
+
{contextMenu}
+
{input}
+
{controls}
+