From e8bb0b12d11a0992ea8c645e43f008239c697bde Mon Sep 17 00:00:00 2001 From: zerone0x Date: Sun, 11 Jan 2026 05:54:46 +0800 Subject: [PATCH] fix(tui): ensure arrow keys work for question selection Add guard clause to validate question data before processing keyboard events, and add stopPropagation() to prevent other handlers from interfering with arrow key navigation in QuestionPrompt. Fixes #7638 Co-Authored-By: Claude Opus 4.5 --- .../src/cli/cmd/tui/routes/session/question.tsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/question.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/question.tsx index e43f4219b98..a0d1a2e11b5 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/question.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/question.tsx @@ -89,15 +89,21 @@ export function QuestionPrompt(props: { request: QuestionRequest }) { const dialog = useDialog() useKeyboard((evt) => { + // Guard: ensure we have valid question data + const currentQuestion = question() + if (!currentQuestion && !confirm()) return + // When editing "Other" textarea if (store.editing && !confirm()) { if (evt.name === "escape") { evt.preventDefault() + evt.stopPropagation() setStore("editing", false) return } if (evt.name === "return") { evt.preventDefault() + evt.stopPropagation() const text = textarea?.plainText?.trim() ?? "" const prev = store.custom[store.tab] @@ -149,6 +155,7 @@ export function QuestionPrompt(props: { request: QuestionRequest }) { if (evt.name === "left" || evt.name === "h") { evt.preventDefault() + evt.stopPropagation() const next = (store.tab - 1 + tabs()) % tabs() setStore("tab", next) setStore("selected", 0) @@ -156,6 +163,7 @@ export function QuestionPrompt(props: { request: QuestionRequest }) { if (evt.name === "right" || evt.name === "l") { evt.preventDefault() + evt.stopPropagation() const next = (store.tab + 1) % tabs() setStore("tab", next) setStore("selected", 0) @@ -164,10 +172,12 @@ export function QuestionPrompt(props: { request: QuestionRequest }) { if (confirm()) { if (evt.name === "return") { evt.preventDefault() + evt.stopPropagation() submit() } if (evt.name === "escape" || keybind.match("app_exit", evt)) { evt.preventDefault() + evt.stopPropagation() reject() } } else { @@ -176,16 +186,19 @@ export function QuestionPrompt(props: { request: QuestionRequest }) { if (evt.name === "up" || evt.name === "k") { evt.preventDefault() + evt.stopPropagation() setStore("selected", (store.selected - 1 + total) % total) } if (evt.name === "down" || evt.name === "j") { evt.preventDefault() + evt.stopPropagation() setStore("selected", (store.selected + 1) % total) } if (evt.name === "return") { evt.preventDefault() + evt.stopPropagation() if (other()) { if (!multi()) { setStore("editing", true) @@ -210,6 +223,7 @@ export function QuestionPrompt(props: { request: QuestionRequest }) { if (evt.name === "escape" || keybind.match("app_exit", evt)) { evt.preventDefault() + evt.stopPropagation() reject() } }