From f713d39c617f79f59eaa3bde18613dafb4c097b5 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Wed, 12 Aug 2026 14:33:53 -0400 Subject: [PATCH] fix(tui): keep interrupt confirmation visible (#42096) --- packages/tui/src/component/prompt/index.tsx | 38 +++++++++++-------- .../cli/tui/prompt-interrupt-status.test.tsx | 25 ++++++++++++ 2 files changed, 48 insertions(+), 15 deletions(-) create mode 100644 packages/tui/test/cli/tui/prompt-interrupt-status.test.tsx diff --git a/packages/tui/src/component/prompt/index.tsx b/packages/tui/src/component/prompt/index.tsx index 44bc0764384..2115fa1b00c 100644 --- a/packages/tui/src/component/prompt/index.tsx +++ b/packages/tui/src/component/prompt/index.tsx @@ -5,6 +5,7 @@ import { MouseEvent, PasteEvent, decodePasteBytes, + type ColorInput, type KeyEvent, } from "@opentui/core" import { createEffect, createMemo, onMount, createSignal, onCleanup, on, Show, Switch, Match, For } from "solid-js" @@ -107,6 +108,22 @@ function fadeColor(color: RGBA, alpha: number) { return RGBA.fromValues(color.r, color.g, color.b, color.a * alpha) } +export function PromptInterruptStatus(props: { + armed: boolean + text: ColorInput + subdued: ColorInput + warning: ColorInput +}) { + return ( + + esc{" "} + + {props.armed ? "again to interrupt" : "interrupt"} + + + ) +} + function hasEditorRangeSelection(selection: EditorSelection["ranges"][number]) { return ( selection.selection.start.line !== selection.selection.end.line || @@ -1804,21 +1821,12 @@ export function Prompt(props: PromptProps) { - 0 ? theme.background.action.primary.default : theme.text.default} - wrapMode="none" - truncate - flexShrink={1} - > - esc{" "} - 0 ? theme.background.action.primary.default : theme.text.subdued, - }} - > - {store.interrupt > 0 ? "again to interrupt" : "interrupt"} - - + 0} + text={theme.text.default} + subdued={theme.text.subdued} + warning={theme.text.feedback.warning.default} + /> diff --git a/packages/tui/test/cli/tui/prompt-interrupt-status.test.tsx b/packages/tui/test/cli/tui/prompt-interrupt-status.test.tsx new file mode 100644 index 00000000000..ebb9269c80f --- /dev/null +++ b/packages/tui/test/cli/tui/prompt-interrupt-status.test.tsx @@ -0,0 +1,25 @@ +/** @jsxImportSource @opentui/solid */ +import { RGBA } from "@opentui/core" +import { testRender } from "@opentui/solid" +import { expect, test } from "bun:test" +import { PromptInterruptStatus } from "../../../src/component/prompt" + +test("armed interrupt status renders visible warning text", async () => { + const text = RGBA.fromHex("#ffffff") + const subdued = RGBA.fromHex("#808080") + const warning = RGBA.fromHex("#fbbf24") + const app = await testRender( + () => , + { width: 30, height: 1 }, + ) + + try { + await app.renderOnce() + const line = app.renderer.currentRenderBuffer.getSpanLines()[0]! + + expect(line.spans.map((span) => span.text).join("")).toContain("esc again to interrupt") + expect(line.spans.filter((span) => span.text.trim()).every((span) => span.fg.equals(warning))).toBeTrue() + } finally { + app.renderer.destroy() + } +})