fix(web): allow multiline input with modifier+Enter in composer (#431)

* fix(web): allow multiline input with modifier+Enter in composer

Previously only Shift+Enter was recognized for newline insertion while
Ctrl+Enter, Alt+Enter, and Cmd+Enter all triggered message send.
This broadens the modifier check so any modifier+Enter inserts a newline.

Also sets submitOnEnter={false} to let the custom handleKeyDown manage
all Enter logic, eliminating dual-handler ambiguity with the library's
built-in submit behavior.

Closes #429

* fix(web): prevent modifier+Enter from accidentally sending messages

Only plain Enter should send; Ctrl/Alt/Cmd+Enter were incorrectly
falling through to the send path because the guard only checked
e.shiftKey. Now all non-Shift modifier combos are blocked from
sending (preventDefault + no-op).

Also keeps submitOnEnter={false} so the custom handleKeyDown is the
sole owner of Enter-key logic, avoiding dual-handler ambiguity.

Closes #429

* fix(web): restore Enter to accept autocomplete suggestions

The previous refactor made the Enter handler unconditionally return
before reaching the suggestion-selection path. Move suggestion
handling above the send/no-op block so Enter still accepts visible
autocomplete entries.
This commit is contained in:
Haoqing Wang
2026-04-11 16:50:36 +08:00
committed by GitHub
parent c62a1eb151
commit 30f8b125a6
@@ -303,10 +303,18 @@ export function HappyComposer(props: {
return // let default textarea behavior handle newline
}
// Enter without shift: send or no-op (never insert newline)
if (key === 'Enter' && !e.shiftKey && suggestions.length === 0) {
// Enter with suggestions visible: select the suggestion
if (key === 'Enter' && suggestions.length > 0) {
e.preventDefault()
if (canSend) {
const indexToSelect = selectedIndex >= 0 ? selectedIndex : 0
handleSuggestionSelect(indexToSelect)
return
}
// Only plain Enter (no modifiers) sends; other modifier combos are ignored
if (key === 'Enter') {
e.preventDefault()
if (!e.ctrlKey && !e.altKey && !e.metaKey && canSend) {
api.composer().send()
setShowContinueHint(false)
}
@@ -324,7 +332,7 @@ export function HappyComposer(props: {
moveDown()
return
}
if ((key === 'Enter' || key === 'Tab') && !e.shiftKey) {
if ((key === 'Tab') && !e.shiftKey) {
e.preventDefault()
const indexToSelect = selectedIndex >= 0 ? selectedIndex : 0
handleSuggestionSelect(indexToSelect)
@@ -768,7 +776,7 @@ export function HappyComposer(props: {
placeholder={showContinueHint ? t('misc.typeMessage') : t('misc.typeAMessage')}
disabled={controlsDisabled}
maxRows={5}
submitOnEnter={!isTouch}
submitOnEnter={false}
cancelOnEscape={false}
onChange={handleChange}
onSelect={handleSelect}