fix(tui): simplify thinking toggle styling (#28487)

This commit is contained in:
Aiden Cline
2026-05-20 15:54:29 -05:00
committed by GitHub
parent 43c24d8d0f
commit f5a8202b41
3 changed files with 50 additions and 24 deletions

View File

@@ -4,6 +4,14 @@
- Local `main` ref may not exist; use `dev` or `origin/dev` for diffs. - Local `main` ref may not exist; use `dev` or `origin/dev` for diffs.
- Prefer automation: execute requested actions without confirmation unless blocked by missing info or safety/irreversibility. - Prefer automation: execute requested actions without confirmation unless blocked by missing info or safety/irreversibility.
## Commits and PR Titles
Use conventional commit-style messages and PR titles: `type(scope): summary`.
Valid types are `feat`, `fix`, `docs`, `chore`, `refactor`, and `test`. Scopes are optional; use the affected package or area when helpful, e.g. `core`, `opencode`, `tui`, `app`, `desktop`, `sdk`, or `plugin`.
Examples: `fix(tui): simplify thinking toggle styling`, `docs: update contributing guide`, `chore(sdk): regenerate types`.
## Style Guide ## Style Guide
### General Principles ### General Principles

View File

@@ -411,12 +411,9 @@ function AssistantReasoning(props: {
<Switch> <Switch>
<Match when={!inMinimal() || expanded()}> <Match when={!inMinimal() || expanded()}>
<box <box
paddingLeft={2} paddingLeft={3}
marginTop={1} marginTop={1}
flexDirection="column" flexDirection="column"
border={["left"]}
customBorderChars={SplitBorder.customBorderChars}
borderColor={theme.backgroundElement}
flexShrink={0} flexShrink={0}
onMouseUp={toggle} onMouseUp={toggle}
> >
@@ -425,17 +422,20 @@ function AssistantReasoning(props: {
drawUnstyledText={false} drawUnstyledText={false}
streaming={true} streaming={true}
syntaxStyle={props.subtleSyntax} syntaxStyle={props.subtleSyntax}
content={(inMinimal() ? " " : "") + "_Thinking:_ " + content()} content={(inMinimal() ? "- " : "") + "_Thinking:_ " + content()}
conceal={true} conceal={true}
fg={theme.textMuted} fg={theme.textMuted}
/> />
</box> </box>
</Match> </Match>
<Match when={isDone()}> <Match when={isDone()}>
<box paddingLeft={3} marginTop={1} flexShrink={0} onMouseUp={toggle}> <box
<text fg={theme.textMuted} wrapMode="none"> paddingLeft={3}
{title() ? "▶ Thought: " + title() : "▶ Thought"} marginTop={1}
</text> flexShrink={0}
onMouseUp={toggle}
>
<CollapsedReasoningText title={title()} />
</box> </box>
</Match> </Match>
<Match when={true}> <Match when={true}>
@@ -448,6 +448,16 @@ function AssistantReasoning(props: {
) )
} }
function CollapsedReasoningText(props: { title: string | null }) {
const { theme } = useTheme()
return (
<text fg={theme.warning} wrapMode="none">
<span style={{ fg: theme.warning, italic: true }}>{props.title ? "+ Thought · " + props.title : "+ Thought"}</span>
</text>
)
}
function AssistantTool(props: { part: SessionMessageAssistantTool; sessionID: string }) { function AssistantTool(props: { part: SessionMessageAssistantTool; sessionID: string }) {
const input = createMemo(() => toolInputRecord(props.part.state.input)) const input = createMemo(() => toolInputRecord(props.part.state.input))
const toolprops = { const toolprops = {

View File

@@ -1533,12 +1533,9 @@ function ReasoningPart(props: { last: boolean; part: ReasoningPart; message: Ass
{/* Full markdown block: `show` mode, or `hide` after the user opens it. */} {/* Full markdown block: `show` mode, or `hide` after the user opens it. */}
<box <box
id={"text-" + props.part.id} id={"text-" + props.part.id}
paddingLeft={2} paddingLeft={3}
marginTop={1} marginTop={1}
flexDirection="column" flexDirection="column"
border={["left"]}
customBorderChars={SplitBorder.customBorderChars}
borderColor={theme.backgroundElement}
onMouseUp={toggle} onMouseUp={toggle}
> >
<code <code
@@ -1546,26 +1543,24 @@ function ReasoningPart(props: { last: boolean; part: ReasoningPart; message: Ass
drawUnstyledText={false} drawUnstyledText={false}
streaming={true} streaming={true}
syntaxStyle={subtleSyntax()} syntaxStyle={subtleSyntax()}
content={(inMinimal() ? " " : "") + (isDone() ? "_Thought:_ " : "_Thinking:_ ") + content()} content={(inMinimal() ? "- " : "") + (isDone() ? "_Thought:_ " : "_Thinking:_ ") + content()}
conceal={ctx.conceal()} conceal={ctx.conceal()}
fg={theme.textMuted} fg={theme.textMuted}
/> />
</box> </box>
</Match> </Match>
<Match when={isDone()}> <Match when={isDone()}>
{/* Settled: ▶ at the start as the click-to-expand cue. */} <box
<box id={"text-" + props.part.id} paddingLeft={3} marginTop={1} flexShrink={0} onMouseUp={toggle}> id={"text-" + props.part.id}
<text fg={theme.textMuted} wrapMode="none"> paddingLeft={3}
{"▶ " + marginTop={1}
(title() flexShrink={0}
? "Thought: " + title() + " · " + Locale.duration(duration()) onMouseUp={toggle}
: "Thought for " + Locale.duration(duration()))} >
</text> <CollapsedReasoningText title={title()} duration={duration()} />
</box> </box>
</Match> </Match>
<Match when={true}> <Match when={true}>
{/* Streaming: leading animated spinner, no disclosure arrow yet — it
snaps in once reasoning settles, signalling "done, click to expand". */}
<box id={"text-" + props.part.id} paddingLeft={3} marginTop={1} flexShrink={0} onMouseUp={toggle}> <box id={"text-" + props.part.id} paddingLeft={3} marginTop={1} flexShrink={0} onMouseUp={toggle}>
<Spinner color={theme.textMuted}>{title() ? "Thinking: " + title() : "Thinking"}</Spinner> <Spinner color={theme.textMuted}>{title() ? "Thinking: " + title() : "Thinking"}</Spinner>
</box> </box>
@@ -1575,6 +1570,19 @@ function ReasoningPart(props: { last: boolean; part: ReasoningPart; message: Ass
) )
} }
function CollapsedReasoningText(props: { title: string | null; duration: number }) {
const { theme } = useTheme()
const duration = () => Locale.duration(props.duration)
return (
<text fg={theme.warning} wrapMode="none">
<span style={{ fg: theme.warning, italic: true }}>
{props.title ? "+ Thought · " + props.title + " · " + duration() : "+ Thought · " + duration()}
</span>
</text>
)
}
function TextPart(props: { last: boolean; part: TextPart; message: AssistantMessage }) { function TextPart(props: { last: boolean; part: TextPart; message: AssistantMessage }) {
const ctx = use() const ctx = use()
const { theme, syntax } = useTheme() const { theme, syntax } = useTheme()