From 3e931152d129669530ea97b80dba64eeb310f0bc Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Thu, 21 May 2026 22:22:51 -0500 Subject: [PATCH] tweak(tui): remove italics from thinking labels (#28737) --- packages/opencode/src/cli/cmd/tui/context/theme.tsx | 5 ++++- .../src/cli/cmd/tui/routes/session/index.tsx | 12 ++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/context/theme.tsx b/packages/opencode/src/cli/cmd/tui/context/theme.tsx index 3829f4488c..33dfd3056d 100644 --- a/packages/opencode/src/cli/cmd/tui/context/theme.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/theme.tsx @@ -49,6 +49,7 @@ type Theme = TuiThemeCurrent & { _hasSelectedListItemText: boolean } type ThemeColor = Exclude +type SyntaxStyleOverrides = Record export function selectedForeground(theme: Theme, bg?: RGBA): RGBA { // If theme explicitly defines selectedListItemText, use it @@ -718,16 +719,18 @@ export function generateSyntax(theme: Theme) { return SyntaxStyle.fromTheme(getSyntaxRules(theme)) } -export function generateSubtleSyntax(theme: Theme) { +export function generateSubtleSyntax(theme: Theme, overrides?: SyntaxStyleOverrides) { const rules = getSyntaxRules(theme) return SyntaxStyle.fromTheme( rules.map((rule) => { + const override = rule.scope.reduce((acc, scope) => ({ ...acc, ...overrides?.[scope] }), {}) if (rule.style.foreground) { const fg = rule.style.foreground return { ...rule, style: { ...rule.style, + ...override, foreground: RGBA.fromInts( Math.round(fg.r * 255), Math.round(fg.g * 255), diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index d10b01670c..ae23d58bcc 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -21,7 +21,7 @@ import { useSync } from "@tui/context/sync" import { useEvent } from "@tui/context/event" import { SplitBorder } from "@tui/component/border" import { Spinner } from "@tui/component/spinner" -import { selectedForeground, useTheme } from "@tui/context/theme" +import { generateSubtleSyntax, selectedForeground, useTheme } from "@tui/context/theme" import { BoxRenderable, ScrollBoxRenderable, addDefaultParsers, TextAttributes, RGBA } from "@opentui/core" import { Prompt, type PromptRef } from "@tui/component/prompt" import type { @@ -1497,7 +1497,7 @@ const PART_MAPPING = { } function ReasoningPart(props: { last: boolean; part: ReasoningPart; message: AssistantMessage }) { - const { theme, subtleSyntax } = useTheme() + const { theme } = useTheme() const ctx = use() // Collapsed by default in hide mode: a single line throughout, so the // layout never shifts. Click to open the full markdown block, click to close. @@ -1519,6 +1519,8 @@ function ReasoningPart(props: { last: boolean; part: ReasoningPart; message: Ass // blocks. Surface the title both while streaming and after settling so the // collapsed line carries real signal, not just a duration. const title = createMemo(() => reasoningTitle(content())) + // Keep markdown emphasis for the existing thinking color/concealment, but render it without italics. + const syntax = createMemo(() => generateSubtleSyntax(theme, { "markup.italic": { italic: false } })) const toggle = () => { if (!inMinimal()) return @@ -1535,7 +1537,9 @@ function ReasoningPart(props: { last: boolean; part: ReasoningPart; message: Ass filetype="markdown" drawUnstyledText={false} streaming={true} - syntaxStyle={subtleSyntax()} + syntaxStyle={syntax()} + // `_Thinking:_`/`_Thought:_` still drives markdown emphasis color and conceals the underscores; + // the syntax override above removes only the italic attribute from that emphasis token. content={(inMinimal() ? "- " : "") + (isDone() ? "_Thought:_ " : "_Thinking:_ ") + content()} conceal={ctx.conceal()} fg={theme.textMuted} @@ -1563,7 +1567,7 @@ function CollapsedReasoningText(props: { title: string | null; duration: number return ( - + {props.title ? "+ Thought: " + props.title + " ยท " + duration() : "+ Thought: " + duration()}