feat(tui): add mouse hover and click support to questions tool (#7905)

This commit is contained in:
indeep99
2026-01-11 22:01:48 -05:00
committed by GitHub
parent 68ed664a3f
commit 82b432349e

View File

@@ -86,6 +86,38 @@ export function QuestionPrompt(props: { request: QuestionRequest }) {
setStore("answers", answers) 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() const dialog = useDialog()
useKeyboard((evt) => { useKeyboard((evt) => {
@@ -149,16 +181,12 @@ export function QuestionPrompt(props: { request: QuestionRequest }) {
if (evt.name === "left" || evt.name === "h") { if (evt.name === "left" || evt.name === "h") {
evt.preventDefault() evt.preventDefault()
const next = (store.tab - 1 + tabs()) % tabs() selectTab((store.tab - 1 + tabs()) % tabs())
setStore("tab", next)
setStore("selected", 0)
} }
if (evt.name === "right" || evt.name === "l") { if (evt.name === "right" || evt.name === "l") {
evt.preventDefault() evt.preventDefault()
const next = (store.tab + 1) % tabs() selectTab((store.tab + 1) % tabs())
setStore("tab", next)
setStore("selected", 0)
} }
if (confirm()) { if (confirm()) {
@@ -176,36 +204,17 @@ export function QuestionPrompt(props: { request: QuestionRequest }) {
if (evt.name === "up" || evt.name === "k") { if (evt.name === "up" || evt.name === "k") {
evt.preventDefault() evt.preventDefault()
setStore("selected", (store.selected - 1 + total) % total) moveTo((store.selected - 1 + total) % total)
} }
if (evt.name === "down" || evt.name === "j") { if (evt.name === "down" || evt.name === "j") {
evt.preventDefault() evt.preventDefault()
setStore("selected", (store.selected + 1) % total) moveTo((store.selected + 1) % total)
} }
if (evt.name === "return") { if (evt.name === "return") {
evt.preventDefault() evt.preventDefault()
if (other()) { selectOption()
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)
} }
if (evt.name === "escape" || keybind.match("app_exit", evt)) { if (evt.name === "escape" || keybind.match("app_exit", evt)) {
@@ -236,6 +245,7 @@ export function QuestionPrompt(props: { request: QuestionRequest }) {
paddingLeft={1} paddingLeft={1}
paddingRight={1} paddingRight={1}
backgroundColor={isActive() ? theme.accent : theme.backgroundElement} backgroundColor={isActive() ? theme.accent : theme.backgroundElement}
onMouseUp={() => selectTab(index())}
> >
<text fg={isActive() ? theme.selectedListItemText : isAnswered() ? theme.text : theme.textMuted}> <text fg={isActive() ? theme.selectedListItemText : isAnswered() ? theme.text : theme.textMuted}>
{q.header} {q.header}
@@ -244,7 +254,12 @@ export function QuestionPrompt(props: { request: QuestionRequest }) {
) )
}} }}
</For> </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> <text fg={confirm() ? theme.selectedListItemText : theme.textMuted}>Confirm</text>
</box> </box>
</box> </box>
@@ -264,7 +279,7 @@ export function QuestionPrompt(props: { request: QuestionRequest }) {
const active = () => i() === store.selected const active = () => i() === store.selected
const picked = () => store.answers[store.tab]?.includes(opt.label) ?? false const picked = () => store.answers[store.tab]?.includes(opt.label) ?? false
return ( return (
<box> <box onMouseOver={() => moveTo(i())} onMouseUp={() => selectOption()}>
<box flexDirection="row" gap={1}> <box flexDirection="row" gap={1}>
<box backgroundColor={active() ? theme.backgroundElement : undefined}> <box backgroundColor={active() ? theme.backgroundElement : undefined}>
<text fg={active() ? theme.secondary : picked() ? theme.success : theme.text}> <text fg={active() ? theme.secondary : picked() ? theme.success : theme.text}>
@@ -280,7 +295,7 @@ export function QuestionPrompt(props: { request: QuestionRequest }) {
) )
}} }}
</For> </For>
<box> <box onMouseOver={() => moveTo(options().length)} onMouseUp={() => selectOption()}>
<box flexDirection="row" gap={1}> <box flexDirection="row" gap={1}>
<box backgroundColor={other() ? theme.backgroundElement : undefined}> <box backgroundColor={other() ? theme.backgroundElement : undefined}>
<text fg={other() ? theme.secondary : customPicked() ? theme.success : theme.text}> <text fg={other() ? theme.secondary : customPicked() ? theme.success : theme.text}>