the disabled composer says why, instead of inviting you to type

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 <noreply@anthropic.com>
This commit is contained in:
2026-08-22 19:35:42 +00:00
co-authored by Claude Opus 5
parent 1c47d0bba7
commit f065e2c0f8
@@ -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"
/>