From 33def8874a5f976bcad6bca48260009f960d4597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Uruchurtu?= Date: Tue, 16 Jun 2026 19:47:30 -0600 Subject: [PATCH] fix(vscode): restore tool preview behavior --- .../kilo-ui/src/components/basic-tool.css | 8 ++-- .../kilo-ui/src/components/message-part.css | 10 ++--- .../kilo-ui/src/components/message-part.tsx | 43 ++++++++++++------- .../tests/unit/font-size-arch.test.ts | 16 +++++++ .../tests/unit/kilo-ui-contract.test.ts | 14 ++++-- .../src/components/chat/TaskToolExpanded.tsx | 2 +- .../webview-ui/src/styles/tool-overrides.css | 8 ---- 7 files changed, 63 insertions(+), 38 deletions(-) diff --git a/packages/kilo-ui/src/components/basic-tool.css b/packages/kilo-ui/src/components/basic-tool.css index 0ff9dd7889..0111b6381a 100644 --- a/packages/kilo-ui/src/components/basic-tool.css +++ b/packages/kilo-ui/src/components/basic-tool.css @@ -194,7 +194,7 @@ html[data-theme="kilo-vscode"] [data-component="tool-part-wrapper"][data-part-ty [data-slot="message-part-title-filename"], [data-slot="message-part-directory-inline"], [data-slot="message-part-meta-line"] { - line-height: 16px; + line-height: var(--kilo-font-size-16); } [data-slot="collapsible-trigger"][aria-expanded="true"] { @@ -271,7 +271,7 @@ html[data-theme="kilo-vscode"] [data-component="tool-part-wrapper"][data-part-ty background: var(--surface-tool-output-base); color: var(--text-weak); font-size: var(--kilo-font-size-12); - line-height: 16px; + line-height: var(--kilo-font-size-16); scrollbar-width: none; &::-webkit-scrollbar { @@ -296,7 +296,7 @@ html[data-theme="kilo-vscode"] [data-component="tool-part-wrapper"][data-part-ty gap: 6px; font-size: var(--kilo-font-size-12); font-weight: var(--font-weight-regular); - line-height: 16px; + line-height: var(--kilo-font-size-16); color: var(--text-weak); } @@ -332,7 +332,7 @@ html[data-theme="kilo-vscode"] [data-component="tool-part-wrapper"][data-part-ty column-gap: 8px; min-height: 20px; font-size: var(--kilo-font-size-12); - line-height: 16px; + line-height: var(--kilo-font-size-16); } [data-component="context-tool-expanded-row"] { diff --git a/packages/kilo-ui/src/components/message-part.css b/packages/kilo-ui/src/components/message-part.css index 657421cee2..bb6cd0f087 100644 --- a/packages/kilo-ui/src/components/message-part.css +++ b/packages/kilo-ui/src/components/message-part.css @@ -438,13 +438,13 @@ html[data-theme="kilo-vscode"] [data-component="todos"] { [data-slot="checkbox-checkbox-label"] { color: var(--text-weak); font-size: var(--kilo-font-size-12); - line-height: 16px; + line-height: var(--kilo-font-size-16); } [data-slot="message-part-todo-hidden"] { color: var(--text-weaker); font-size: var(--kilo-font-size-12); - line-height: 16px; + line-height: var(--kilo-font-size-16); } [data-slot="message-part-todo-content"][data-changed="changed"] { @@ -630,7 +630,7 @@ html[data-theme="kilo-vscode"] [data-component="reasoning-part"] { color: var(--text-weak); font-size: var(--kilo-font-size-12); font-weight: var(--font-weight-regular); - line-height: 16px; + line-height: var(--kilo-font-size-16); [data-component="icon"] { color: var(--text-weak); @@ -641,7 +641,7 @@ html[data-theme="kilo-vscode"] [data-component="reasoning-part"] { [data-slot="reasoning-title"] { color: var(--text-weak); font-weight: var(--font-weight-regular); - line-height: 16px; + line-height: var(--kilo-font-size-16); } [data-slot="reasoning-label"] + [data-slot="reasoning-title"]::before { @@ -675,7 +675,7 @@ html[data-theme="kilo-vscode"] [data-component="reasoning-part"] { [data-component="markdown"] { font-size: var(--kilo-font-size-12); - line-height: 16px; + line-height: var(--kilo-font-size-16); } } } diff --git a/packages/kilo-ui/src/components/message-part.tsx b/packages/kilo-ui/src/components/message-part.tsx index 6af2c7852c..3bc87340fa 100644 --- a/packages/kilo-ui/src/components/message-part.tsx +++ b/packages/kilo-ui/src/components/message-part.tsx @@ -2114,24 +2114,39 @@ function BashCopyButton(props: { value: () => string; label: string }) { ) } -function BashHighlightedOutput(props: { cmd: string; output: string; outputPath?: string }) { +function BashHighlightedOutput(props: { cmd: string; output: string; outputPath?: string; active?: boolean }) { const data = useData() const i18n = useI18n() - const state = { signal: { aborted: false } } - let ref: HTMLDivElement | undefined + const cmdState = { signal: { aborted: false } } + const outState = { signal: { aborted: false } } + let cmdRef: HTMLDivElement | undefined + let outRef: HTMLDivElement | undefined createEffect(() => { - state.signal.aborted = true + cmdState.signal.aborted = true + if (!props.active) return const cmd = props.cmd - if (!ref || !cmd) return + if (!cmdRef || !cmd) return const signal = { aborted: false } - state.signal = signal - ref.innerHTML = `
${escapeHtml(cmd)}
` - void deferredHighlight(ref, undefined, signal) + cmdState.signal = signal + cmdRef.innerHTML = `
${escapeHtml(cmd)}
` + void deferredHighlight(cmdRef, undefined, signal) + }) + + createEffect(() => { + outState.signal.aborted = true + if (!props.active) return + const out = props.output + if (!outRef || !out) return + const signal = { aborted: false } + outState.signal = signal + outRef.innerHTML = `
${escapeHtml(out)}
` + void deferredHighlight(outRef, undefined, signal) }) onCleanup(() => { - state.signal.aborted = true + cmdState.signal.aborted = true + outState.signal.aborted = true }) const openInEditor = () => { @@ -2152,7 +2167,7 @@ function BashHighlightedOutput(props: { cmd: string; output: string; outputPath? -
+
props.cmd} label={i18n.t("ui.message.copy")} />
@@ -2162,11 +2177,7 @@ function BashHighlightedOutput(props: { cmd: string; output: string; outputPath?
-
-
-                {props.output}
-              
-
+
@@ -2236,7 +2247,7 @@ ToolRegistry.register({ } > - + ) diff --git a/packages/kilo-vscode/tests/unit/font-size-arch.test.ts b/packages/kilo-vscode/tests/unit/font-size-arch.test.ts index 36d3a9daea..2bd3610614 100644 --- a/packages/kilo-vscode/tests/unit/font-size-arch.test.ts +++ b/packages/kilo-vscode/tests/unit/font-size-arch.test.ts @@ -102,6 +102,22 @@ describe("webview font-size architecture", () => { ).toEqual([]) }) + it("uses scalable line heights in polished tool previews", () => { + const files = [ + path.join(REPO, "packages/kilo-ui/src/components/basic-tool.css"), + path.join(REPO, "packages/kilo-ui/src/components/message-part.css"), + ] + const violations = files.flatMap((file) => { + const src = stripComments(fs.readFileSync(file, "utf-8")) + return Array.from( + src.matchAll(/line-height\s*:\s*\d+(?:\.\d+)?px\b/g), + (match) => `${rel(file)}:${line(src, match.index ?? 0)}`, + ) + }) + + expect(violations).toEqual([]) + }) + it("injects and live-broadcasts the webview font-size setting to all webview providers", () => { const util = fs.readFileSync(path.join(ROOT, "src/utils.ts"), "utf-8") expect(util, "buildWebviewHtml must seed webview font tokens before app code runs").toContain("getWebviewFontSize") diff --git a/packages/kilo-vscode/tests/unit/kilo-ui-contract.test.ts b/packages/kilo-vscode/tests/unit/kilo-ui-contract.test.ts index 8e399a49fb..6bc25cc4a2 100644 --- a/packages/kilo-vscode/tests/unit/kilo-ui-contract.test.ts +++ b/packages/kilo-vscode/tests/unit/kilo-ui-contract.test.ts @@ -202,15 +202,21 @@ describe("Bash tool static terminal preview (source)", () => { it("BashHighlightedOutput syntax highlights the command next to the prompt", () => { expect(src).toContain('data-slot="bash-terminal" data-kind="command"') expect(src).toContain('data-slot="bash-prompt"') - expect(src).toContain('data-slot="bash-section-code" data-scrollable ref={ref}') + expect(src).toContain('data-slot="bash-section-code" data-scrollable ref={cmdRef}') expect(src).toContain('data-lang="shellscript"') expect(src).toContain("escapeHtml(cmd)") }) - it("BashHighlightedOutput renders output as plain code", () => { + it("BashHighlightedOutput syntax highlights log output", () => { expect(src).toContain('data-slot="bash-terminal" data-kind="output"') - expect(src).toMatch(/
\s*\{props\.output\}<\/code>\s*<\/pre>/)
-    expect(src).not.toMatch(/data-lang="log"/)
+    expect(src).toContain('data-slot="bash-section-code" data-scrollable ref={outRef}')
+    expect(src).toContain('data-lang="log"')
+    expect(src).toContain("escapeHtml(out)")
+  })
+
+  it("BashHighlightedOutput highlights only while expanded", () => {
+    expect(src).toContain("if (!props.active) return")
+    expect(block).toContain("active={open()}")
   })
 
   it("BashHighlightedOutput keeps command and output in separate terminal containers", () => {
diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/TaskToolExpanded.tsx b/packages/kilo-vscode/webview-ui/src/components/chat/TaskToolExpanded.tsx
index 9f093a998f..62162fda12 100644
--- a/packages/kilo-vscode/webview-ui/src/components/chat/TaskToolExpanded.tsx
+++ b/packages/kilo-vscode/webview-ui/src/components/chat/TaskToolExpanded.tsx
@@ -122,7 +122,7 @@ const TaskToolRenderer: Component = (props) => {
   )
 
   return (
-    
+