From f065e2c0f8e7f45433e44e1920f51d13d8fd7a8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Sat, 22 Aug 2026 19:35:42 +0000 Subject: [PATCH] the disabled composer says why, instead of inviting you to type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Caught in a screenshot before any testing: the new-commander composer was correctly disabled and still read "Type a message...". `placeholder` was declared TWICE on the same textarea — the reason I added, and the original below it — and JSX takes the last one. So the gate worked and was completely invisible, which is the worst version: an input that refuses you without saying what it wants. One placeholder now, carrying the reason when disabled and the usual text otherwise. Fourth prop-shaped mistake today, and a new variant: not a prop that does not exist, but a real prop silently overwritten by a second copy of itself. A typecheck cannot see either. Co-Authored-By: Claude Opus 5 --- .../officerdev/src/apps/Chat/components/InputArea.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/workspaces/officerdev/src/apps/Chat/components/InputArea.tsx b/src/workspaces/officerdev/src/apps/Chat/components/InputArea.tsx index ee6a3f60..600fdb6b 100644 --- a/src/workspaces/officerdev/src/apps/Chat/components/InputArea.tsx +++ b/src/workspaces/officerdev/src/apps/Chat/components/InputArea.tsx @@ -115,7 +115,6 @@ export const InputArea = ({ manager, disabled }: InputAreaProps) => { // Native `disabled`, not a click guard: it also takes the field out of the tab order and stops a // paste, which a guard on send would not. disabled={!!disabled} - placeholder={disabled ? disabled.reason : undefined} onChange={(ev) => setInput(ev.target.value)} onKeyDown={(ev) => { // Enter is how anybody actually sends, so the interception has to be here as well as on the @@ -143,7 +142,10 @@ export const InputArea = ({ manager, disabled }: InputAreaProps) => { } } }} - placeholder="Type a message..." + // One placeholder, not two. It was declared twice on this element — the reason above and this + // below — and JSX takes the LAST, so the gate was applied and completely invisible: a disabled + // composer still inviting you to type a message. + placeholder={disabled ? disabled.reason : 'Type a message...'} rows={1} className="min-w-0 flex-1 resize-none rounded-lg border border-input bg-background/80 px-2 py-1.5 md:px-3 md:py-2 text-base md:text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-duck-teal/30 focus:border-duck-teal/50" />