diff options
| author | Akshar Patel <[email protected]> | 2026-02-05 21:11:08 -0500 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-02-05 20:11:08 -0600 |
| commit | 683d234d805e4d1097751d3cd583117856e41de5 (patch) | |
| tree | e2240b06eaa2fe2aa2f9d2471070ef43e2eaf99a /packages | |
| parent | 229cdafcc43ef53611a12dc2e8137575669e8706 (diff) | |
| download | opencode-683d234d805e4d1097751d3cd583117856e41de5.tar.gz opencode-683d234d805e4d1097751d3cd583117856e41de5.zip | |
feat(tui): highlight esc label on hover in dialog (#12383)
Diffstat (limited to 'packages')
8 files changed, 95 insertions, 29 deletions
diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx index 93e76cbdf..f8be5577b 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx @@ -124,6 +124,7 @@ function AutoMethod(props: AutoMethodProps) { const dialog = useDialog() const sync = useSync() const toast = useToast() + const [hover, setHover] = createSignal(false) useKeyboard((evt) => { if (evt.name === "c" && !evt.ctrl && !evt.meta) { @@ -154,9 +155,16 @@ function AutoMethod(props: AutoMethodProps) { <text attributes={TextAttributes.BOLD} fg={theme.text}> {props.title} </text> - <text fg={theme.textMuted} onMouseUp={() => dialog.clear()}> - esc - </text> + <box + paddingLeft={1} + paddingRight={1} + backgroundColor={hover() ? theme.primary : undefined} + onMouseOver={() => setHover(true)} + onMouseOut={() => setHover(false)} + onMouseUp={() => dialog.clear()} + > + <text fg={hover() ? theme.selectedListItemText : theme.textMuted}>esc</text> + </box> </box> <box gap={1}> <Link href={props.authorization.url} fg={theme.primary} /> diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-status.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-status.tsx index 3e6e30951..e2ab579a9 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-status.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-status.tsx @@ -2,7 +2,7 @@ import { TextAttributes } from "@opentui/core" import { useTheme } from "../context/theme" import { useDialog } from "@tui/ui/dialog" import { useSync } from "@tui/context/sync" -import { For, Match, Switch, Show, createMemo } from "solid-js" +import { For, Match, Switch, Show, createMemo, createSignal } from "solid-js" import { Installation } from "@/installation" export type DialogStatusProps = {} @@ -11,6 +11,7 @@ export function DialogStatus() { const sync = useSync() const { theme } = useTheme() const dialog = useDialog() + const [hover, setHover] = createSignal(false) const enabledFormatters = createMemo(() => sync.data.formatter.filter((f) => f.enabled)) @@ -45,9 +46,16 @@ export function DialogStatus() { <text fg={theme.text} attributes={TextAttributes.BOLD}> Status </text> - <text fg={theme.textMuted} onMouseUp={() => dialog.clear()}> - esc - </text> + <box + paddingLeft={1} + paddingRight={1} + backgroundColor={hover() ? theme.primary : undefined} + onMouseOver={() => setHover(true)} + onMouseOut={() => setHover(false)} + onMouseUp={() => dialog.clear()} + > + <text fg={hover() ? theme.selectedListItemText : theme.textMuted}>esc</text> + </box> </box> <text fg={theme.textMuted}>OpenCode v{Installation.VERSION}</text> <Show when={Object.keys(sync.data.mcp).length > 0} fallback={<text fg={theme.text}>No MCP Servers</text>}> diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-alert.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-alert.tsx index 642c73b48..8b4b61476 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-alert.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-alert.tsx @@ -2,6 +2,7 @@ import { TextAttributes } from "@opentui/core" import { useTheme } from "../context/theme" import { useDialog, type DialogContext } from "./dialog" import { useKeyboard } from "@opentui/solid" +import { createSignal } from "solid-js" export type DialogAlertProps = { title: string @@ -12,6 +13,7 @@ export type DialogAlertProps = { export function DialogAlert(props: DialogAlertProps) { const dialog = useDialog() const { theme } = useTheme() + const [hover, setHover] = createSignal(false) useKeyboard((evt) => { if (evt.name === "return") { @@ -25,9 +27,16 @@ export function DialogAlert(props: DialogAlertProps) { <text attributes={TextAttributes.BOLD} fg={theme.text}> {props.title} </text> - <text fg={theme.textMuted} onMouseUp={() => dialog.clear()}> - esc - </text> + <box + paddingLeft={1} + paddingRight={1} + backgroundColor={hover() ? theme.primary : undefined} + onMouseOver={() => setHover(true)} + onMouseOut={() => setHover(false)} + onMouseUp={() => dialog.clear()} + > + <text fg={hover() ? theme.selectedListItemText : theme.textMuted}>esc</text> + </box> </box> <box paddingBottom={1}> <text fg={theme.textMuted}>{props.message}</text> diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-confirm.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-confirm.tsx index b86bd4325..7d9b74cde 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-confirm.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-confirm.tsx @@ -2,7 +2,7 @@ import { TextAttributes } from "@opentui/core" import { useTheme } from "../context/theme" import { useDialog, type DialogContext } from "./dialog" import { createStore } from "solid-js/store" -import { For } from "solid-js" +import { createSignal, For } from "solid-js" import { useKeyboard } from "@opentui/solid" import { Locale } from "@/util/locale" @@ -16,6 +16,7 @@ export type DialogConfirmProps = { export function DialogConfirm(props: DialogConfirmProps) { const dialog = useDialog() const { theme } = useTheme() + const [hover, setHover] = createSignal(false) const [store, setStore] = createStore({ active: "confirm" as "confirm" | "cancel", }) @@ -37,9 +38,16 @@ export function DialogConfirm(props: DialogConfirmProps) { <text attributes={TextAttributes.BOLD} fg={theme.text}> {props.title} </text> - <text fg={theme.textMuted} onMouseUp={() => dialog.clear()}> - esc - </text> + <box + paddingLeft={1} + paddingRight={1} + backgroundColor={hover() ? theme.primary : undefined} + onMouseOver={() => setHover(true)} + onMouseOut={() => setHover(false)} + onMouseUp={() => dialog.clear()} + > + <text fg={hover() ? theme.selectedListItemText : theme.textMuted}>esc</text> + </box> </box> <box paddingBottom={1}> <text fg={theme.textMuted}>{props.message}</text> diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-export-options.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-export-options.tsx index 1e8d09bb0..957467c5d 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-export-options.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-export-options.tsx @@ -2,7 +2,7 @@ import { TextareaRenderable, TextAttributes } from "@opentui/core" import { useTheme } from "../context/theme" import { useDialog, type DialogContext } from "./dialog" import { createStore } from "solid-js/store" -import { onMount, Show, type JSX } from "solid-js" +import { createSignal, onMount, Show, type JSX } from "solid-js" import { useKeyboard } from "@opentui/solid" export type DialogExportOptionsProps = { @@ -25,6 +25,7 @@ export function DialogExportOptions(props: DialogExportOptionsProps) { const dialog = useDialog() const { theme } = useTheme() let textarea: TextareaRenderable + const [hover, setHover] = createSignal(false) const [store, setStore] = createStore({ thinking: props.defaultThinking, toolDetails: props.defaultToolDetails, @@ -80,9 +81,16 @@ export function DialogExportOptions(props: DialogExportOptionsProps) { <text attributes={TextAttributes.BOLD} fg={theme.text}> Export Options </text> - <text fg={theme.textMuted} onMouseUp={() => dialog.clear()}> - esc - </text> + <box + paddingLeft={1} + paddingRight={1} + backgroundColor={hover() ? theme.primary : undefined} + onMouseOver={() => setHover(true)} + onMouseOut={() => setHover(false)} + onMouseUp={() => dialog.clear()} + > + <text fg={hover() ? theme.selectedListItemText : theme.textMuted}>esc</text> + </box> </box> <box gap={1}> <box> diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-help.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-help.tsx index 4e4527930..f56347d4a 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-help.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-help.tsx @@ -3,11 +3,13 @@ import { useTheme } from "@tui/context/theme" import { useDialog } from "./dialog" import { useKeyboard } from "@opentui/solid" import { useKeybind } from "@tui/context/keybind" +import { createSignal } from "solid-js" export function DialogHelp() { const dialog = useDialog() const { theme } = useTheme() const keybind = useKeybind() + const [hover, setHover] = createSignal(false) useKeyboard((evt) => { if (evt.name === "return" || evt.name === "escape") { @@ -21,9 +23,16 @@ export function DialogHelp() { <text attributes={TextAttributes.BOLD} fg={theme.text}> Help </text> - <text fg={theme.textMuted} onMouseUp={() => dialog.clear()}> - esc/enter - </text> + <box + paddingLeft={1} + paddingRight={1} + backgroundColor={hover() ? theme.primary : undefined} + onMouseOver={() => setHover(true)} + onMouseOut={() => setHover(false)} + onMouseUp={() => dialog.clear()} + > + <text fg={hover() ? theme.selectedListItemText : theme.textMuted}>esc/enter</text> + </box> </box> <box paddingBottom={1}> <text fg={theme.textMuted}> diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-prompt.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-prompt.tsx index b1b05a0f1..03814e17d 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-prompt.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-prompt.tsx @@ -1,7 +1,7 @@ import { TextareaRenderable, TextAttributes } from "@opentui/core" import { useTheme } from "../context/theme" import { useDialog, type DialogContext } from "./dialog" -import { onMount, type JSX } from "solid-js" +import { createSignal, onMount, type JSX } from "solid-js" import { useKeyboard } from "@opentui/solid" export type DialogPromptProps = { @@ -17,6 +17,7 @@ export function DialogPrompt(props: DialogPromptProps) { const dialog = useDialog() const { theme } = useTheme() let textarea: TextareaRenderable + const [hover, setHover] = createSignal(false) useKeyboard((evt) => { if (evt.name === "return") { @@ -39,9 +40,16 @@ export function DialogPrompt(props: DialogPromptProps) { <text attributes={TextAttributes.BOLD} fg={theme.text}> {props.title} </text> - <text fg={theme.textMuted} onMouseUp={() => dialog.clear()}> - esc - </text> + <box + paddingLeft={1} + paddingRight={1} + backgroundColor={hover() ? theme.primary : undefined} + onMouseOver={() => setHover(true)} + onMouseOut={() => setHover(false)} + onMouseUp={() => dialog.clear()} + > + <text fg={hover() ? theme.selectedListItemText : theme.textMuted}>esc</text> + </box> </box> <box gap={1}> {props.description} diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx index 490a10072..7792900bc 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx @@ -1,7 +1,7 @@ import { InputRenderable, RGBA, ScrollBoxRenderable, TextAttributes } from "@opentui/core" import { useTheme, selectedForeground } from "@tui/context/theme" import { entries, filter, flatMap, groupBy, pipe, take } from "remeda" -import { batch, createEffect, createMemo, For, Show, type JSX, on } from "solid-js" +import { batch, createEffect, createMemo, createSignal, For, Show, type JSX, on } from "solid-js" import { createStore } from "solid-js/store" import { useKeyboard, useTerminalDimensions } from "@opentui/solid" import * as fuzzysort from "fuzzysort" @@ -49,6 +49,7 @@ export type DialogSelectRef<T> = { export function DialogSelect<T>(props: DialogSelectProps<T>) { const dialog = useDialog() const { theme } = useTheme() + const [hover, setHover] = createSignal(false) const [store, setStore] = createStore({ selected: 0, filter: "", @@ -226,9 +227,16 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) { <text fg={theme.text} attributes={TextAttributes.BOLD}> {props.title} </text> - <text fg={theme.textMuted} onMouseUp={() => dialog.clear()}> - esc - </text> + <box + paddingLeft={1} + paddingRight={1} + backgroundColor={hover() ? theme.primary : undefined} + onMouseOver={() => setHover(true)} + onMouseOut={() => setHover(false)} + onMouseUp={() => dialog.clear()} + > + <text fg={hover() ? theme.selectedListItemText : theme.textMuted}>esc</text> + </box> </box> <box paddingTop={1}> <input |
