Skip to content

feat(web): configurable composer send key#2393

Open
jappyjan wants to merge 1 commit intopingdotgg:mainfrom
jappyjan:feat/composer-send-key-setting
Open

feat(web): configurable composer send key#2393
jappyjan wants to merge 1 commit intopingdotgg:mainfrom
jappyjan:feat/composer-send-key-setting

Conversation

@jappyjan
Copy link
Copy Markdown

@jappyjan jappyjan commented Apr 28, 2026

Summary

Add a "Composer send key" setting (server-synced via `UnifiedSettings`) with three options:

  • Enter (default, current behavior): Enter sends, Shift+Enter newlines
  • Shift + Enter: Shift+Enter sends, Enter newlines
  • Send button only: neither key sends, only the dedicated send button

Why

On a phone the soft keyboard's Enter key sends partial messages on every tap, which is wrong for a touch UX. "Send button only" fixes that without forcing one heuristic on everyone — vim/editor users may prefer "Shift + Enter" on desktop, etc.

The default preserves existing desktop behavior, so this is an additive change with no migration concerns. The slash-command / mention menu's Enter-to-confirm path is unchanged — the menu branch fires before the send branch in `onComposerCommandKey`.

Files

  • `packages/contracts/src/settings.ts`: new `ComposerSendKey` literal, field on `ServerSettings` + `ServerSettingsPatch`. Decoding default keeps existing settings files compatible.
  • `apps/web/src/components/settings/SettingsPanels.tsx`: new `SettingsRow` between "New threads" and "Add project starts in", using the same Select pattern as `defaultThreadEnvMode`.
  • `apps/web/src/components/chat/ChatComposer.tsx`: replace the unconditional `Enter && !shiftKey` send branch with a settings-driven check.

Test plan

  • Settings → General shows the new "Composer send key" row with three options and a reset button when non-default
  • "Enter" mode: Enter sends, Shift+Enter inserts newline (= current default behavior)
  • "Shift + Enter" mode: Shift+Enter sends, Enter inserts newline
  • "Send button only" mode: neither Enter nor Shift+Enter sends; the send button still does
  • Slash-command menu: open, hit Enter — still selects the highlighted command in all three modes
  • Setting persists across reload (server-synced)
  • Existing settings files without the field decode cleanly (defaults to "Enter")

Screenshots / video

925A1689-F0ED-4D91-90A8-1F833B85A350_1_102_o

Note

Add configurable send key option to the chat composer

  • Introduces a composerSendKey setting with three options: enter (default), shift-enter, or button-only, replacing the hardcoded Enter-to-send behavior in ChatComposer.tsx.
  • Adds the setting schema and default ('enter') to settings.ts, including support for partial patch updates.
  • Exposes a UI control in the General settings panel to view, change, and reset the send key preference.
  • Behavioral Change: users who previously relied on Enter to send will see no change (default is preserved), but the behavior is now user-overridable.

Macroscope summarized cdcf825.


Note

Medium Risk
Changes message-submission key handling in ChatComposer, which can impact UX and prevent/trigger unintended sends, but is gated by a new setting with a default matching prior behavior.

Overview
Adds a new server-synced composerSendKey setting (default enter) with options for Enter, Shift+Enter, or Send button only, including schema/defaults and patch support.

Exposes this preference in the General settings panel with a select control, reset support, and inclusion in the “restore defaults” dirty-check list.

Updates ChatComposer key handling so onSend fires only when the configured send keystroke is pressed, while leaving menu selection (Enter/Tab) behavior unchanged.

Reviewed by Cursor Bugbot for commit cdcf825. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features
    • Introduced customizable composer send key setting. Users can now configure their preferred keyboard shortcut for sending messages through General preferences: Enter, Shift+Enter, or Send button only. Settings persist across all sessions and synchronize across devices.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 28, 2026

📝 Walkthrough

Walkthrough

A new configurable composer send key setting is implemented across the application layers. The feature allows users to choose between three options: Enter, Shift+Enter, or button-only sending. Changes include adding the setting schema definition, updating the keyboard event handler to respect the configured key, and adding UI controls in the settings panel.

Changes

Cohort / File(s) Summary
Settings Schema Definition
packages/contracts/src/settings.ts
Adds ComposerSendKey schema (union of "enter", "shift-enter", "button-only"), default constant, and integrates into ServerSettings and ServerSettingsPatch types.
Chat Composer Keyboard Logic
apps/web/src/components/chat/ChatComposer.tsx
Updates onComposerCommandKey to compute wantsSend based on settings.composerSendKey instead of hardcoded Enter behavior, respecting Shift modifier accordingly.
Settings UI Panel
apps/web/src/components/settings/SettingsPanels.tsx
Adds a new row in General settings with a selectable dropdown for composer send key, persists changes via updateSettings(), and conditionally displays reset control.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A carrot key to send with glee,
Or shift-press too, whichever's free!
The composer bows to user's wish,
One tap, one hold—configuration's delish!
No more confusion, just smooth delight! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(web): configurable composer send key' clearly and specifically summarizes the main change—adding a user-configurable setting for the chat composer's send key behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description is well-structured and comprehensive, covering all template sections with clear explanations of the change, reasoning, affected files, test plan, and supporting screenshots.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Apr 28, 2026
@jappyjan jappyjan marked this pull request as ready for review April 28, 2026 21:55
@jappyjan
Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 28, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/components/settings/SettingsPanels.tsx`:
- Around line 1019-1066: The global restore logic is not detecting changes to
the new composerSendKey setting; update useSettingsRestore to include
"composerSendKey" in the changedSettingLabels array so that changedSettingLabels
(and the early-return check) will detect this setting as dirty; locate the
useSettingsRestore implementation and add "composerSendKey" alongside the other
setting keys referenced in changedSettingLabels so restores and
SettingResetButton behavior work correctly with SettingsPanels' composerSendKey
control.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4ac44262-17b6-4038-8177-709620aae3f1

📥 Commits

Reviewing files that changed from the base of the PR and between dbebc38 and 9b980ee.

📒 Files selected for processing (3)
  • apps/web/src/components/chat/ChatComposer.tsx
  • apps/web/src/components/settings/SettingsPanels.tsx
  • packages/contracts/src/settings.ts

Comment on lines +1019 to +1066
<SettingsRow
title="Composer send key"
description="Choose which keystroke submits the composer. Use 'Send button only' on touch devices to avoid accidental sends from the soft keyboard's Enter."
resetAction={
settings.composerSendKey !== DEFAULT_UNIFIED_SETTINGS.composerSendKey ? (
<SettingResetButton
label="composer send key"
onClick={() =>
updateSettings({
composerSendKey: DEFAULT_UNIFIED_SETTINGS.composerSendKey,
})
}
/>
) : null
}
control={
<Select
value={settings.composerSendKey}
onValueChange={(value) => {
if (value === "enter" || value === "shift-enter" || value === "button-only") {
updateSettings({ composerSendKey: value });
}
}}
>
<SelectTrigger className="w-full sm:w-44" aria-label="Composer send key">
<SelectValue>
{settings.composerSendKey === "shift-enter"
? "Shift + Enter"
: settings.composerSendKey === "button-only"
? "Send button only"
: "Enter"}
</SelectValue>
</SelectTrigger>
<SelectPopup align="end" alignItemWithTrigger={false}>
<SelectItem hideIndicator value="enter">
Enter
</SelectItem>
<SelectItem hideIndicator value="shift-enter">
Shift + Enter
</SelectItem>
<SelectItem hideIndicator value="button-only">
Send button only
</SelectItem>
</SelectPopup>
</Select>
}
/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add composerSendKey to global restore-dirty tracking.

The new setting is configurable here, but useSettingsRestore does not include it in changedSettingLabels. If this is the only modified setting, global restore can no-op because of the early return at Line [512].

Suggested patch
diff --git a/apps/web/src/components/settings/SettingsPanels.tsx b/apps/web/src/components/settings/SettingsPanels.tsx
@@
       ...(settings.defaultThreadEnvMode !== DEFAULT_UNIFIED_SETTINGS.defaultThreadEnvMode
         ? ["New thread mode"]
         : []),
+      ...(settings.composerSendKey !== DEFAULT_UNIFIED_SETTINGS.composerSendKey
+        ? ["Composer send key"]
+        : []),
       ...(settings.addProjectBaseDirectory !== DEFAULT_UNIFIED_SETTINGS.addProjectBaseDirectory
         ? ["Add project base directory"]
         : []),
@@
       settings.defaultThreadEnvMode,
+      settings.composerSendKey,
       settings.diffWordWrap,
       settings.enableAssistantStreaming,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/components/settings/SettingsPanels.tsx` around lines 1019 -
1066, The global restore logic is not detecting changes to the new
composerSendKey setting; update useSettingsRestore to include "composerSendKey"
in the changedSettingLabels array so that changedSettingLabels (and the
early-return check) will detect this setting as dirty; locate the
useSettingsRestore implementation and add "composerSendKey" alongside the other
setting keys referenced in changedSettingLabels so restores and
SettingResetButton behavior work correctly with SettingsPanels' composerSendKey
control.

Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 9b980ee. Configure here.

Comment thread apps/web/src/components/settings/SettingsPanels.tsx
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp Bot commented Apr 28, 2026

Approvability

Verdict: Approved

Self-contained user preference feature adding configurable composer send key options. Default behavior preserved, schema-validated input, and the concern raised in the review comment appears already addressed in the current diff.

You can customize Macroscope's approvability policy. Learn more.

Add a "Composer send key" setting (server-synced via UnifiedSettings)
with three options:

- "Enter" (default, current behavior): Enter sends, Shift+Enter newlines
- "Shift + Enter": Shift+Enter sends, Enter newlines
- "Send button only": neither key sends, only the dedicated send button

The default preserves existing desktop behavior. "Send button only" is
intended for touch devices where the soft keyboard's Enter key
otherwise sends partial messages on every tap. The slash-command/
mention menu's Enter-to-confirm path is unchanged because the menu
branch fires before the send branch.

UI lives in the existing General settings panel, between "New threads"
and "Add project starts in", as a Select control matching the
established settings-row pattern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jappyjan jappyjan force-pushed the feat/composer-send-key-setting branch from 9b980ee to cdcf825 Compare April 28, 2026 22:00
Copy link
Copy Markdown
Contributor

@gameroman gameroman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to #2335 but looks better I think

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants