From f0742dd4f988f26f78f3db93b2ab3090f55bf618 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Sun, 26 Apr 2026 15:23:06 -0400 Subject: [PATCH] fix: use readOnly (not disabled) to lock textarea during stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The form-submit handler in chat.html was setting ``textarea.disabled = true`` synchronously before the browser actually serialized the form. Disabled form fields are excluded from submission, so the request body contained ``prose=""`` even when the user had typed text — which the server (correctly) rejected with the new empty-prose 400. Net effect: typing "hello" + Send gave a "prose cannot be empty" error. Switched to ``readOnly``: same UX (user can't edit while streaming) but the field IS submitted. The unlock path now also clears the textarea and refocuses for the next turn. --- chat/templates/chat.html | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/chat/templates/chat.html b/chat/templates/chat.html index 8833062..c2f622c 100644 --- a/chat/templates/chat.html +++ b/chat/templates/chat.html @@ -78,7 +78,11 @@ document.querySelector('.drawer-toggle')?.addEventListener('click', (e) => { function unlock() { isStreaming = false; if (sendBtn) sendBtn.disabled = false; - if (textarea) textarea.disabled = false; + if (textarea) { + textarea.readOnly = false; + textarea.value = ''; + textarea.focus(); + } const stop = shell.querySelector('.stop-streaming'); if (stop) stop.remove(); } @@ -128,7 +132,10 @@ document.querySelector('.drawer-toggle')?.addEventListener('click', (e) => { form.addEventListener('submit', () => { isStreaming = true; if (sendBtn) sendBtn.disabled = true; - if (textarea) textarea.disabled = true; + // readOnly (not disabled) — disabled fields are excluded from the + // form submission, which would send prose="" and trigger the + // server's empty-prose 400. + if (textarea) textarea.readOnly = true; if (!shell.querySelector('.stop-streaming')) { const stopBtn = document.createElement('button'); stopBtn.type = 'button';