diff options
| author | indeep99 <[email protected]> | 2026-01-11 22:01:48 -0500 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-01-11 22:01:48 -0500 |
| commit | 82b432349e4063f612f54758ba78999b75cf13fb (patch) | |
| tree | b8f57c2fa18bf8296265bd4841c6795c883e958c | |
| parent | 68ed664a3f08c64061af0781bbcc345ebd245f5a (diff) | |
| download | opencode-82b432349e4063f612f54758ba78999b75cf13fb.tar.gz opencode-82b432349e4063f612f54758ba78999b75cf13fb.zip | |
feat(tui): add mouse hover and click support to questions tool (#7905)
| -rw-r--r-- | packages/opencode/src/cli/cmd/tui/routes/session/question.tsx | 77 |
1 files changed, 46 insertions, 31 deletions
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 e43f4219b..c6518ec3f 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/question.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/question.tsx @@ -86,6 +86,38 @@ export function QuestionPrompt(props: { request: QuestionRequest }) { setStore("answers", answers) } + function moveTo(index: number) { + setStore("selected", index) + } + + function selectTab(index: number) { + setStore("tab", index) + setStore("selected", 0) + } + + function selectOption() { + if (other()) { + if (!multi()) { + setStore("editing", true) + return + } + const value = input() + if (value && customPicked()) { + toggle(value) + return + } + setStore("editing", true) + return + } + const opt = options()[store.selected] + if (!opt) return + if (multi()) { + toggle(opt.label) + return + } + pick(opt.label) + } + const dialog = useDialog() useKeyboard((evt) => { @@ -149,16 +181,12 @@ export function QuestionPrompt(props: { request: QuestionRequest }) { if (evt.name === "left" || evt.name === "h") { evt.preventDefault() - const next = (store.tab - 1 + tabs()) % tabs() - setStore("tab", next) - setStore("selected", 0) + selectTab((store.tab - 1 + tabs()) % tabs()) } if (evt.name === "right" || evt.name === "l") { evt.preventDefault() - const next = (store.tab + 1) % tabs() - setStore("tab", next) - setStore("selected", 0) + selectTab((store.tab + 1) % tabs()) } if (confirm()) { @@ -176,36 +204,17 @@ export function QuestionPrompt(props: { request: QuestionRequest }) { if (evt.name === "up" || evt.name === "k") { evt.preventDefault() - setStore("selected", (store.selected - 1 + total) % total) + moveTo((store.selected - 1 + total) % total) } if (evt.name === "down" || evt.name === "j") { evt.preventDefault() - setStore("selected", (store.selected + 1) % total) + moveTo((store.selected + 1) % total) } if (evt.name === "return") { evt.preventDefault() - if (other()) { - if (!multi()) { - setStore("editing", true) - return - } - const value = input() - if (value && customPicked()) { - toggle(value) - return - } - setStore("editing", true) - return - } - const opt = opts[store.selected] - if (!opt) return - if (multi()) { - toggle(opt.label) - return - } - pick(opt.label) + selectOption() } if (evt.name === "escape" || keybind.match("app_exit", evt)) { @@ -236,6 +245,7 @@ export function QuestionPrompt(props: { request: QuestionRequest }) { paddingLeft={1} paddingRight={1} backgroundColor={isActive() ? theme.accent : theme.backgroundElement} + onMouseUp={() => selectTab(index())} > <text fg={isActive() ? theme.selectedListItemText : isAnswered() ? theme.text : theme.textMuted}> {q.header} @@ -244,7 +254,12 @@ export function QuestionPrompt(props: { request: QuestionRequest }) { ) }} </For> - <box paddingLeft={1} paddingRight={1} backgroundColor={confirm() ? theme.accent : theme.backgroundElement}> + <box + paddingLeft={1} + paddingRight={1} + backgroundColor={confirm() ? theme.accent : theme.backgroundElement} + onMouseUp={() => selectTab(questions().length)} + > <text fg={confirm() ? theme.selectedListItemText : theme.textMuted}>Confirm</text> </box> </box> @@ -264,7 +279,7 @@ export function QuestionPrompt(props: { request: QuestionRequest }) { const active = () => i() === store.selected const picked = () => store.answers[store.tab]?.includes(opt.label) ?? false return ( - <box> + <box onMouseOver={() => moveTo(i())} onMouseUp={() => selectOption()}> <box flexDirection="row" gap={1}> <box backgroundColor={active() ? theme.backgroundElement : undefined}> <text fg={active() ? theme.secondary : picked() ? theme.success : theme.text}> @@ -280,7 +295,7 @@ export function QuestionPrompt(props: { request: QuestionRequest }) { ) }} </For> - <box> + <box onMouseOver={() => moveTo(options().length)} onMouseUp={() => selectOption()}> <box flexDirection="row" gap={1}> <box backgroundColor={other() ? theme.backgroundElement : undefined}> <text fg={other() ? theme.secondary : customPicked() ? theme.success : theme.text}> |
