feat(ui): add enter-to-submit toggle for prompt input

This commit is contained in:
Shantur Rathore
2026-02-07 19:18:39 +00:00
parent ca28f503b7
commit e0bb867948
11 changed files with 128 additions and 7 deletions

View File

@@ -16,6 +16,7 @@ import { getCommands } from "../stores/commands"
import { showAlertDialog } from "../stores/alerts"
import { useI18n } from "../lib/i18n"
import { getLogger } from "../lib/logger"
import { preferences } from "../stores/preferences"
const log = getLogger("actions")
@@ -542,13 +543,46 @@ export default function PromptInput(props: PromptInputProps) {
}
}
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
e.preventDefault()
if (showPicker()) {
handlePickerClose()
if (e.key === "Enter") {
const isModified = e.metaKey || e.ctrlKey
// If the picker is open, Enter should select from it.
if (!isModified && showPicker()) {
return
}
if (submitOnEnter()) {
// Swapped mode: Enter submits, Cmd/Ctrl+Enter inserts a newline.
if (isModified) {
e.preventDefault()
e.stopPropagation()
insertNewlineAtCursor()
return
}
// Shift+Enter always inserts a newline.
if (e.shiftKey) {
// If the picker is open, avoid selecting an item on Enter.
if (showPicker()) {
e.stopPropagation()
}
return
}
e.preventDefault()
handleSend()
return
}
// Default: Cmd/Ctrl+Enter submits.
if (isModified) {
e.preventDefault()
if (showPicker()) {
handlePickerClose()
}
handleSend()
return
}
handleSend()
return
}
if (e.key === "ArrowUp") {
@@ -1056,6 +1090,25 @@ export default function PromptInput(props: PromptInputProps) {
: { key: "!", text: t("promptInput.hints.shell.enable") }
const commandHint = () => ({ key: "/", text: t("promptInput.hints.commands") })
const submitOnEnter = () => preferences().promptSubmitOnEnter
function insertNewlineAtCursor() {
const textarea = textareaRef
const current = prompt()
const start = textarea ? textarea.selectionStart : current.length
const end = textarea ? textarea.selectionEnd : current.length
const nextValue = current.substring(0, start) + "\n" + current.substring(end)
const nextCursor = start + 1
setPrompt(nextValue)
setTimeout(() => {
if (!textareaRef) return
textareaRef.focus()
textareaRef.setSelectionRange(nextCursor, nextCursor)
}, 0)
}
const shouldShowOverlay = () => prompt().length === 0
const instance = () => getActiveInstance()
@@ -1142,7 +1195,19 @@ export default function PromptInput(props: PromptInputProps) {
fallback={
<>
<span class="prompt-overlay-text">
<Kbd>Enter</Kbd> {t("promptInput.overlay.newLine")} <Kbd shortcut="cmd+enter" /> {t("promptInput.overlay.send")} <Kbd>@</Kbd> {t("promptInput.overlay.filesAgents")} <Kbd></Kbd> {t("promptInput.overlay.history")}
<Show
when={submitOnEnter()}
fallback={
<>
<Kbd>Enter</Kbd> {t("promptInput.overlay.newLine")} <Kbd shortcut="cmd+enter" /> {t("promptInput.overlay.send")}
</>
}
>
<>
<Kbd>Enter</Kbd> {t("promptInput.overlay.send")} <Kbd shortcut="cmd+enter" /> {t("promptInput.overlay.newLine")}
</>
</Show>
{" "} <Kbd>@</Kbd> {t("promptInput.overlay.filesAgents")} <Kbd></Kbd> {t("promptInput.overlay.history")}
</span>
<Show when={attachments().length > 0}>
<span class="prompt-overlay-text prompt-overlay-muted">{t("promptInput.overlay.attachments", { count: attachments().length })}</span>