dialog prompt submit keybind + opentui event sink (#27945)

This commit is contained in:
Sebastian
2026-05-18 00:23:19 +02:00
committed by GitHub
parent e92b1fe7d7
commit f97e115ee2
9 changed files with 256 additions and 61 deletions

View File

@@ -188,6 +188,7 @@ export const Definitions = {
"dialog.select.home": keybind("home", "Move to first dialog item"),
"dialog.select.end": keybind("end", "Move to last dialog item"),
"dialog.select.submit": keybind("return", "Submit selected dialog item"),
"dialog.prompt.submit": keybind("return", "Submit dialog prompt"),
"dialog.mcp.toggle": keybind("space", "Toggle MCP in MCP dialog"),
"prompt.autocomplete.prev": keybind("up,ctrl+p", "Move to previous autocomplete item"),
"prompt.autocomplete.next": keybind("down,ctrl+n", "Move to next autocomplete item"),

View File

@@ -1,8 +1,10 @@
import { TextareaRenderable, TextAttributes } from "@opentui/core"
import { useTheme } from "../context/theme"
import { useDialog, type DialogContext } from "./dialog"
import { Show, createEffect, onMount, type JSX } from "solid-js"
import { Show, createEffect, createSignal, onMount, type JSX } from "solid-js"
import { Spinner } from "../component/spinner"
import { useTuiConfig } from "../context/tui-config"
import { useBindings, useCommandShortcut } from "../keymap"
export type DialogPromptProps = {
title: string
@@ -18,8 +20,32 @@ export type DialogPromptProps = {
export function DialogPrompt(props: DialogPromptProps) {
const dialog = useDialog()
const { theme } = useTheme()
const tuiConfig = useTuiConfig()
const submitShortcut = useCommandShortcut("dialog.prompt.submit")
const [textareaTarget, setTextareaTarget] = createSignal<TextareaRenderable>()
let textarea: TextareaRenderable
function confirm() {
if (props.busy) return
props.onConfirm?.(textarea.plainText)
}
useBindings(() => ({
target: textareaTarget,
enabled: textareaTarget() !== undefined && !props.busy,
// Dialog form semantics must win over the global managed textarea input layer.
priority: 1,
commands: [
{
name: "dialog.prompt.submit",
title: "Submit dialog prompt",
category: "Dialog",
run: confirm,
},
],
bindings: tuiConfig.keybinds.gather("dialog.prompt", ["dialog.prompt.submit"]),
}))
onMount(() => {
dialog.setSize("medium")
setTimeout(() => {
@@ -59,13 +85,10 @@ export function DialogPrompt(props: DialogPromptProps) {
<box gap={1}>
{props.description}
<textarea
onSubmit={() => {
if (props.busy) return
props.onConfirm?.(textarea.plainText)
}}
height={3}
ref={(val: TextareaRenderable) => {
textarea = val
setTextareaTarget(val)
}}
initialValue={props.value}
placeholder={props.placeholder ?? "Enter text"}
@@ -80,9 +103,11 @@ export function DialogPrompt(props: DialogPromptProps) {
</box>
<box paddingBottom={1} gap={1} flexDirection="row">
<Show when={!props.busy} fallback={<text fg={theme.textMuted}>processing...</text>}>
<text fg={theme.text}>
enter <span style={{ fg: theme.textMuted }}>submit</span>
</text>
<Show when={submitShortcut()}>
<text fg={theme.text}>
{submitShortcut()} <span style={{ fg: theme.textMuted }}>submit</span>
</text>
</Show>
</Show>
</box>
</box>