style(tui): simplify the composer surface

This commit is contained in:
Xubin Ren
2026-08-17 20:56:10 +08:00
parent f17d9eeff7
commit 9d7453a53e
2 changed files with 60 additions and 11 deletions
+39 -2
View File
@@ -766,7 +766,13 @@ describe("NanobotTui layout", () => {
const internals = app as unknown as {
palette: { referenceBackground: string; text: string; border: string }
shell: { backgroundColor: { intent: string } }
composer: { backgroundColor: { intent: string }; textColor: { toInts(): number[] } }
composerFrame: {
backgroundColor: { intent: string; toInts(): number[] }
}
composer: {
backgroundColor: { intent: string; toInts(): number[] }
textColor: { toInts(): number[] }
}
transcript: {
markdown: Set<{ syntaxStyle: object }>
frames: Set<{ borderColor: { toInts(): number[] } }>
@@ -791,13 +797,44 @@ describe("NanobotTui layout", () => {
border: "#D4D4D8",
})
expect(internals.shell.backgroundColor.intent).toBe("default")
expect(internals.composer.backgroundColor.intent).toBe("default")
expect(internals.composerFrame.backgroundColor.toInts().slice(0, 3)).toEqual([240, 240, 240])
expect(internals.composer.backgroundColor.toInts().slice(0, 3)).toEqual([240, 240, 240])
expect(internals.composer.textColor.toInts().slice(0, 3)).toEqual([24, 24, 27])
expect(sessionFrame?.borderColor.toInts().slice(0, 3)).toEqual([212, 212, 216])
expect(userRow?.backgroundColor.toInts().slice(0, 3)).toEqual([240, 240, 240])
expect(markdown?.syntaxStyle).not.toBe(darkSyntax)
})
test("uses a quiet surface instead of a boxed composer", async () => {
setup = await createRenderer({ width: 72, height: 20, screenMode: "alternate-screen" })
const app = NanobotTui.mount(
setup.renderer,
{ ...options, theme: "light" },
client(),
new MockTreeSitterClient({ autoResolveTimeout: 0 }),
)
const internals = app as unknown as {
ready: boolean
composerFrame: {
border: boolean | string[]
backgroundColor: { toInts(): number[] }
}
composer: { backgroundColor: { toInts(): number[] } }
}
expect(internals.composerFrame.border).toBeFalse()
expect(internals.composerFrame.backgroundColor.toInts().slice(0, 3)).toEqual([240, 240, 240])
expect(internals.composer.backgroundColor.toInts().slice(0, 3)).toEqual([240, 240, 240])
app.accept({ event: "attached", chat_id: "chat" })
await waitUntil(() => internals.ready)
await setup.renderOnce()
const composerLine = setup.captureCharFrame().split("\n")
.find((line) => line.includes("Ask nanobot anything")) || ""
expect(composerLine).not.toContain("│")
})
test("uses asymmetric roles instead of chat bubbles", async () => {
setup = await createRenderer({ width: 72, height: 24, screenMode: "alternate-screen" })
const app = NanobotTui.mount(
+21 -9
View File
@@ -411,17 +411,16 @@ export class NanobotTui {
})
this.title.add(this.titleText)
this.title.add(this.modelText)
const composerSurface = this.composerSurface()
this.composerFrame = new BoxRenderable(renderer, {
id: "nanobot-tui-composer-frame",
width: "100%",
minHeight: 3,
minHeight: 1,
flexShrink: 0,
border: true,
borderStyle: "rounded",
borderColor: this.palette.border,
border: false,
paddingLeft: 1,
paddingRight: 1,
backgroundColor: RGBA.defaultBackground(),
backgroundColor: composerSurface,
})
this.composer = new TextareaRenderable(renderer, {
id: "nanobot-tui-composer",
@@ -433,8 +432,8 @@ export class NanobotTui {
placeholderColor: this.palette.faint,
textColor: this.palette.text,
focusedTextColor: this.palette.text,
backgroundColor: RGBA.defaultBackground(),
focusedBackgroundColor: RGBA.defaultBackground(),
backgroundColor: composerSurface,
focusedBackgroundColor: composerSurface,
cursorColor: this.palette.accent,
showCursor: true,
keyBindings: [
@@ -1040,7 +1039,7 @@ export class NanobotTui {
this.sessionMenu.setTheme(commandMenuTheme(this.palette))
this.contextPanel.setTheme(contextPanelTheme(this.palette))
this.diffViewer.setTheme(diffViewerTheme(this.palette, this.backgroundKnown))
this.composerFrame.borderColor = this.palette.border
this.updateComposerAppearance()
this.composer.textColor = this.palette.text
this.composer.focusedTextColor = this.palette.text
this.composer.cursorColor = this.palette.accent
@@ -1113,7 +1112,20 @@ export class NanobotTui {
private resizeComposer(): void {
const maxHeight = Math.max(1, Math.min(12, Math.floor(this.renderer.height / 3)))
this.composer.maxHeight = maxHeight
this.composerFrame.maxHeight = maxHeight + 2
this.composerFrame.maxHeight = maxHeight
}
private composerSurface(): RGBA {
return this.backgroundKnown
? RGBA.fromHex(this.palette.userBackground)
: RGBA.defaultBackground()
}
private updateComposerAppearance(): void {
const surface = this.composerSurface()
this.composerFrame.backgroundColor = surface
this.composer.backgroundColor = surface
this.composer.focusedBackgroundColor = surface
}
private syncComposerPlaceholder(): void {