Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/tui/src/mini/footer.form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,12 @@ import {
} from "./form.shared"
import type { FormBodyState } from "./form.shared"
import type { RunFooterTheme } from "./theme"
import type { FormCancel, FormReply, MiniFormRequest } from "./types"
import type { FormCancel, FormReply, MiniFormRequest, RunTuiConfig } from "./types"

export function RunFormBody(props: {
request: MiniFormRequest
theme: RunFooterTheme
cursor?: RunTuiConfig["cursor"]
onReply: (input: FormReply) => void | Promise<void>
onCancel: (input: FormCancel) => void | Promise<void>
openExternal?: (url: string) => Promise<unknown>
Expand Down Expand Up @@ -320,6 +321,7 @@ export function RunFormBody(props: {
backgroundColor={props.theme.surface}
focusedBackgroundColor={props.theme.surface}
cursorColor={props.theme.text}
cursorStyle={props.cursor}
focused
onSubmit={commitInput}
onContentChange={() => {
Expand Down
6 changes: 5 additions & 1 deletion packages/tui/src/mini/footer.permission.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import {
import { footerWidthPolicy } from "./footer.width"
import { toolFiletype } from "./tool"
import { transparent, type RunBlockTheme, type RunFooterTheme } from "./theme"
import type { MiniPermissionRequest, PermissionReply } from "./types"
import type { MiniPermissionRequest, PermissionReply, RunTuiConfig } from "./types"
import { PatchDiff } from "../component/patch-diff"

function buttons(
Expand Down Expand Up @@ -74,6 +74,7 @@ function buttons(
/** @internal Exported to test managed textarea submission without permission navigation. */
export function RejectField(props: {
theme: RunFooterTheme
cursor?: RunTuiConfig["cursor"]
text: string
disabled: boolean
onChange: (text: string) => void
Expand Down Expand Up @@ -113,6 +114,7 @@ export function RejectField(props: {
backgroundColor={props.theme.surface}
focusedBackgroundColor={props.theme.surface}
cursorColor={props.theme.text}
cursorStyle={props.cursor}
focused={!props.disabled}
onSubmit={props.onConfirm}
onContentChange={() => {
Expand All @@ -139,6 +141,7 @@ export function RunPermissionBody(props: {
request: MiniPermissionRequest
directory?: () => string
theme: RunFooterTheme
cursor?: RunTuiConfig["cursor"]
block: RunBlockTheme
onReply: (input: PermissionReply) => void | Promise<void>
mono?: boolean
Expand Down Expand Up @@ -327,6 +330,7 @@ export function RunPermissionBody(props: {
<box width={narrow() ? "100%" : undefined} flexGrow={1} flexShrink={1}>
<RejectField
theme={props.theme}
cursor={props.cursor}
text={state().message}
disabled={busy()}
onChange={(text) => {
Expand Down
3 changes: 3 additions & 0 deletions packages/tui/src/mini/footer.prompt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import type {
RunPrompt,
RunPromptPart,
RunReference,
RunTuiConfig,
} from "./types"

const AUTOCOMPLETE_ROWS = FOOTER_MENU_ROWS
Expand Down Expand Up @@ -175,6 +176,7 @@ export function selectedCommand(text: string, command: RunPrompt["command"]) {

export function RunPromptBody(props: {
theme: () => RunFooterTheme
cursor?: RunTuiConfig["cursor"]
background: () => ColorInput
placeholder: () => StyledText | string
onSubmit: () => void
Expand Down Expand Up @@ -239,6 +241,7 @@ export function RunPromptBody(props: {
backgroundColor={props.background()}
focusedBackgroundColor={props.background()}
cursorColor={props.theme().text}
cursorStyle={props.cursor}
onSubmit={props.onSubmit}
onKeyDown={props.onKeyDown}
onPaste={() => {
Expand Down
1 change: 1 addition & 0 deletions packages/tui/src/mini/footer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ export class RunFooter implements FooterApi {
variants: footer.variants,
currentVariant: footer.currentVariant,
theme: footer.theme,
cursor: options.tuiConfig.cursor,
mono: options.mono,
miniSettings: footer.miniSettings,
history: footer.history,
Expand Down
5 changes: 5 additions & 0 deletions packages/tui/src/mini/footer.view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import type {
RunPrompt,
RunProvider,
RunReference,
RunTuiConfig,
} from "./types"
import type { RunTheme } from "./theme"

Expand Down Expand Up @@ -92,6 +93,7 @@ type RunFooterViewProps = {
subagent?: () => FooterSubagentState
queuedPrompts?: () => FooterQueuedPrompt[]
theme: () => RunTheme
cursor?: RunTuiConfig["cursor"]
mono: boolean
miniSettings: () => MiniSettings
history?: () => RunPrompt[]
Expand Down Expand Up @@ -733,6 +735,7 @@ export function RunFooterView(props: RunFooterViewProps) {
<Match when={active().type === "prompt" && route().type === "composer"}>
<RunPromptBody
theme={theme}
cursor={props.cursor}
background={() => runTheme().background}
placeholder={composer.placeholder}
onSubmit={composer.onSubmit}
Expand Down Expand Up @@ -882,6 +885,7 @@ export function RunFooterView(props: RunFooterViewProps) {
request={permission()!.request}
directory={props.directory}
theme={theme()}
cursor={props.cursor}
block={block()}
onReply={props.onPermissionReply}
mono={props.mono}
Expand All @@ -893,6 +897,7 @@ export function RunFooterView(props: RunFooterViewProps) {
<RunFormBody
request={value.request}
theme={theme()}
cursor={props.cursor}
state={formStates.get(value.request.id) ?? createFormBodyState(value.request)}
onState={(state) => {
if (!formsAbsent && !settledForms.has(state.formID))
Expand Down
2 changes: 1 addition & 1 deletion packages/tui/src/mini/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ export type FormCancel = {
location?: LocationRef
}

export type RunTuiConfig = Pick<Config.Resolved, "keybinds" | "leader" | "theme" | "mini" | "session">
export type RunTuiConfig = Pick<Config.Resolved, "keybinds" | "leader" | "theme" | "mini" | "session" | "cursor">

export type MiniSettings = {
thinking: "show" | "hide"
Expand Down
13 changes: 13 additions & 0 deletions packages/tui/test/mini/footer.view.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ async function renderFooter(
subagent={subagents}
queuedPrompts={() => input.queuedPrompts ?? []}
theme={input.theme ?? (() => RUN_THEME_FALLBACK)}
cursor={config.cursor}
mono={input.mono ?? false}
miniSettings={miniSettings}
onSubmit={input.onSubmit ?? (() => true)}
Expand Down Expand Up @@ -342,6 +343,18 @@ test("direct footer composer area does not adopt footer surface", async () => {
}
})

test("direct footer composer uses the configured cursor style", async () => {
const cursor = { style: "underline" as const, blinking: false }
const app = await renderFooter({ tuiConfig: { ...tuiConfig, cursor } })

try {
await app.renderOnce()
expect(app.renderer.currentFocusedEditor?.cursorStyle).toEqual(cursor)
} finally {
app.cleanup()
}
})

test("run entry content updates when live commit text changes", async () => {
const [commit, setCommit] = createSignal<StreamCommit>({
kind: "tool",
Expand Down
Loading