diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx index 3240afab326..c412e11f0f3 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx @@ -566,7 +566,13 @@ export function Autocomplete(props: { } if (name === "return") { select() - e.preventDefault() + // After selection, autocomplete is hidden. If the key that triggered + // this is also the submit keybinding, we need to let the event + // propagate so the prompt can handle submission. + // Only prevent default if autocomplete is still visible (selection failed). + if (store.visible) { + e.preventDefault() + } return } if (name === "tab") { diff --git a/packages/opencode/src/cli/cmd/tui/component/textarea-keybindings.ts b/packages/opencode/src/cli/cmd/tui/component/textarea-keybindings.ts index 36ab03de545..d7df599ed7d 100644 --- a/packages/opencode/src/cli/cmd/tui/component/textarea-keybindings.ts +++ b/packages/opencode/src/cli/cmd/tui/component/textarea-keybindings.ts @@ -64,10 +64,25 @@ export function useTextareaKeybindings() { return createMemo(() => { const keybinds = keybind.all - return [ - { name: "return", action: "submit" }, - { name: "return", meta: true, action: "newline" }, - ...TEXTAREA_ACTIONS.flatMap((action) => mapTextareaKeybindings(keybinds, action)), - ] satisfies KeyBinding[] + // Get user-defined bindings first + const userBindings = TEXTAREA_ACTIONS.flatMap((action) => + mapTextareaKeybindings(keybinds, action), + ) + + // Check if user has configured each action + const hasSubmitBinding = userBindings.some((b) => b.action === "submit") + const hasNewlineBinding = userBindings.some((b) => b.action === "newline") + + // Build defaults array, only adding defaults for unconfigured actions + const defaults: KeyBinding[] = [] + if (!hasSubmitBinding) { + defaults.push({ name: "return", action: "submit" }) + } + if (!hasNewlineBinding) { + defaults.push({ name: "return", meta: true, action: "newline" }) + } + + // User bindings come first so they take precedence over defaults + return [...userBindings, ...defaults] satisfies KeyBinding[] }) }