fix(web): keep send reachable while a turn is running on mobile - #4781
fix(web): keep send reachable while a turn is running on mobile#4781AMohamedAakhil wants to merge 5 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Approved Straightforward mobile UX bug fix that adds a send button alongside stop when a turn is running (since Enter-to-send is unavailable on mobile). Self-contained to chat composer with good test coverage and no impact on desktop behavior. You can customize Macroscope's approvability policy. Learn more. |
On viewports below `sm` there is no way to send a follow-up while a turn is running. `ComposerPrimaryActions` replaces the submit button with the stop button whenever `isRunning` is set, and `shouldSubmitComposerOnEnter` returns false on mobile viewports, so the keyboard path that desktop users rely on does not exist there. Sending mid-run is already supported: `onSend` has no `isRunning` guard and `isSendBusy` tracks the local dispatch rather than the turn state. Desktop reaches it with Enter. This only makes the same action reachable by touch. Adds `showSendWhileRunning`, wired to `isMobileViewport`, which renders the send button next to stop while a turn runs and the composer has content. Desktop rendering is unchanged. The running branch moves below the send button so both can be rendered without duplicating markup. That reorders it past the plan follow-up branch, which is inert: `showPlanFollowUpPrompt` requires `latestTurnSettled`, so it cannot be set while a turn is running. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
484c7e6 to
627d963
Compare
Dismissing prior approval to re-evaluate 627d963
|
@juliusmarminge can you please take a look at this 👀 |
|
Some extra context that may help triage this. This is a recent regression, not long-standing behavior. It lands hardest on T3 Connect. #4775 has a report reproducing it over a managed relay tunnel from an iPhone on 5G. With Connect now GA you can reach an agent from your phone on any network, but you cannot interject once a turn starts, which removes most of the value of remote control for anything longer than a quick question. Their workaround is a useful confirmation of the cause: rotating to landscape crosses the Status: checks are green, non-test diff is +29/-17 across two files, and desktop rendering is unchanged since No rush if this collides with the Steer and Queue work in #231. Happy to close it if that already covers the mobile affordance. |
Fixes #4775
What Changed
On viewports below
sm, there is no way to send a follow-up while a turn is running.Two guards overlap and between them leave no send path:
ComposerPrimaryActions.tsxreturns only the stop button wheneverisRunningis set, replacing the submit button.shouldSubmitComposerOnEnterincomposer-logic.tsreturns!isMobileViewport && !shiftKey, so Enter never submits belowsm.This adds a
showSendWhileRunningprop, wired toisMobileViewport, that renders the send button next to stop while a turn is running and the composer has sendable content. Desktop rendering is unchanged.To render both buttons without duplicating markup, the running branch moves below the send button, which becomes a
sendButtonconst. That reorders it past the plan follow-up branch, which is inert:showPlanFollowUpPromptrequireslatestTurnSettled, so it cannot be set while a turn is running.Non-test diff is +29 / -17 across two files.
Why
Sending mid-run is already supported.
onSendinChatView.tsxhas noisRunningguard, andisSendBusyisactiveLocalDispatch !== nullrather than the turn state. Desktop users reach that path by pressing Enter. Mobile has no path to it at all.So this is not a new follow-up mode, and it takes no position on queue vs steer semantics (#231). It only makes an action the app already supports reachable by touch.
The collapsed mobile composer hides how sharp this is. It passes
isRunning={false}(ChatComposer.tsx:2748, :3032), so it shows a send arrow while a turn runs. But tapping it to type expands the composer, and the expanded footer is where send is swapped for stop. The affordance is only visible while you cannot type into it.UI Changes
Captured in a real browser at 390x844 against a dev server, with a turn running and text typed in the composer.
Before, stop is the only action:
After, send sits next to stop:
Enumerating the composer's visible buttons in the same states gives
["Stop generation"]before and["Stop generation", "Send message"]after.No visual change on desktop:
showSendWhileRunningdefaults tofalse, and the only caller passesisMobileViewport.Tests
ComposerPrimaryActions.test.tsbecame.test.tsxso the component can be rendered withrenderToStaticMarkup, matchingComposerBannerStack.test.tsx. Three cases added:vp test run apps/web/src/components/chat/ComposerPrimaryActions.test.tsxpasses 11/11.vp lintandvp fmt --checkare clean, andvp run --filter @t3tools/web typecheckexits 0.Checklist
Note
Low Risk
Localized composer UI and prop wiring; send while running was already supported server-side—this only exposes it on mobile.
Overview
Mobile users can send follow-up messages while a turn is still running by showing Send next to Stop when the composer has sendable content. Desktop behavior is unchanged (
showSendWhileRunningdefaults tofalse).Previously,
ComposerPrimaryActionsreplaced the submit control with only Stop wheneverisRunningwas true, and Enter-to-send is disabled belowsm, so mobile had no touch path to an already-supported send flow.ChatComposernow passesshowSendWhileRunning={isMobileViewport}.The send control is built once as a shared
sendButton; when not running it is returned alone; when running, stop is shown and send is added only ifshowSendWhileRunning && hasSendableContent. Tests cover stop-only (desktop / empty composer) vs stop+send on mobile.Reviewed by Cursor Bugbot for commit 9affbce. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Show Send button alongside Stop button during a running turn on mobile viewports
On mobile, Enter-to-send is unavailable, so users had no way to send a new message while a turn was running. This adds a
showSendWhileRunningprop toComposerPrimaryActionsthat, when true and content is sendable, renders the Send button alongside the Stop button.ChatComposerpassesisMobileViewportas this prop value.Macroscope summarized 9affbce.