feat(chat): bare Enter sends on fine-pointer devices, Shift+Enter newline (ADR-0031) #71
No reviewers
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/coding-lab!71
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "afk/70"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Bare Enter now submits both web composers — the chat reply textarea (
RunChat.tsx) and the new-run composer (NewRun.tsx) — on fine-pointer devices, per the maintainer grill session of 2026-07-09. Touch devices keep return-as-newline and the on-screen Send button.What changed
web/src/lib/composerKeys.ts(isComposerSend): one pure predicate both composers call, so they cannot drift. Encodes the whole contract:matchMedia('(hover: hover) and (pointer: fine)')matches — evaluated per keydown (never snapshotted), so docking/undocking a keyboard on hybrids behaves; absence ofmatchMediareads as not-fine-pointer.isComposing/ legacykeyCode === 229Enter never sends (previously absent inweb/src; required once bare Enter can send).preventDefault-ed (no stray leading newline). InNewRunspecifically, bare Enter on an empty box must not launch a plain spawn — while Cmd/Ctrl+Enter (and the Start button) keep that explicit empty-spawn path.NewRunStart buttontitle→ "Start run (Enter)".enterkeyhintchange, no user-facing toggle, no Go/API/provider change — pure SPA diff plus ADR.Tests
558/558 green (37 files); lint, prettier, and
tsc --noEmit && vite buildall clean.working.matchMediaprofiles (bare Enter inert, Ctrl+Enter sends),isComposingguard, empty-boxpreventDefault, popover-accept precedence under fine-pointer.NewRuncomposer, including pinning Cmd/Ctrl+Enter's empty plain-spawn and the new tooltip.ADR
docs/adr/0031-composer-bare-enter-sends-on-fine-pointer.mdrecords the pinned decisions and rejected options (enterkeyhint, settings toggle, mount-time snapshot, UA sniffing, skipping the IME guard, per-composer duplication). ADR-0022 (incl. its now-overturned rejected option) and ADR-0029 are annotated in place; everything else in ADR-0029 (always-Send, no queue, header Interrupt) remains in force.Closes #70
🤖 Generated with Claude Code
https://claude.ai/code/session_0191AABRn5vPgRUSkck4oTgg
Bare Enter now submits both web composers (chat reply, new-run spawn) on devices with a mouse/trackpad — gated per keydown on matchMedia('(hover: hover) and (pointer: fine)') so hybrids that dock or undock a keyboard stay correct. Touch devices keep return-as-newline and the on-screen Send button, preserving the phone-first rationale of ADR-0005/0022. Shift/Alt+Enter fall through as newlines everywhere; Cmd/Ctrl+Enter keeps sending in all environments and all agent states (ADR-0029's always-send contract now extends to bare Enter). The gate lives in one shared predicate, web/src/lib/composerKeys.ts (isComposerSend), so the two composers cannot drift. It adds the previously missing IME guard (isComposing / legacy keyCode 229) — safe to omit under Ctrl+Enter, required under bare Enter. Bare Enter on an empty box never sends and is preventDefault-ed (no stray leading newline); in NewRun it also must not launch a plain spawn, while Cmd/Ctrl+Enter keeps that explicit empty-spawn path. Slash-command popover precedence is unchanged. NewRun's Start tooltip becomes "Start run (Enter)". ADR-0031 records the decision and partially supersedes ADR-0022/0029 (their bare-Enter-stays-a-newline clauses, including ADR-0022's rejected-option entry); both files are annotated in place. Closes #70 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0191AABRn5vPgRUSkck4oTgg