fix(tui): refine thinking block styling

This commit is contained in:
Dax Raad
2026-07-14 15:26:04 -04:00
parent 016545513f
commit 6039f54126
+76 -66
View File
@@ -1090,6 +1090,7 @@ function SessionReasoningGroupView(props: {
const { theme, syntax } = useTheme() const { theme, syntax } = useTheme()
const renderer = useRenderer() const renderer = useRenderer()
const [expanded, setExpanded] = createSignal(false) const [expanded, setExpanded] = createSignal(false)
const [hover, setHover] = createSignal(false)
const parts = createMemo<{ message: SessionMessageAssistant; part: SessionMessageAssistantReasoning }[]>( const parts = createMemo<{ message: SessionMessageAssistant; part: SessionMessageAssistantReasoning }[]>(
(previous) => { (previous) => {
const next = props.refs.flatMap((ref) => { const next = props.refs.flatMap((ref) => {
@@ -1127,61 +1128,56 @@ function SessionReasoningGroupView(props: {
<For each={parts()}>{(item) => <ReasoningPart part={item.part} message={item.message} last={false} />}</For> <For each={parts()}>{(item) => <ReasoningPart part={item.part} message={item.message} last={false} />}</For>
} }
> >
<box paddingLeft={3} flexDirection="column" flexShrink={0}> <box flexDirection="column" flexShrink={0}>
<box <InlineToolRow
icon={expanded() ? "-" : "+"}
color={
!props.completed
? theme.text
: hover() || expanded()
? theme.warning
: RGBA.fromValues(theme.warning.r, theme.warning.g, theme.warning.b, theme.thinkingOpacity)
}
complete={props.completed}
pending={latest() ? `Thinking: ${latest()}` : "Thinking"}
spinner={!props.completed}
onMouseOver={() => setHover(true)}
onMouseOut={() => setHover(false)}
onMouseUp={() => { onMouseUp={() => {
if (renderer.getSelection()?.getSelectedText()) return if (renderer.getSelection()?.getSelectedText()) return
setExpanded((value) => !value) setExpanded((value) => !value)
}} }}
> >
<Show {props.completed ? "Thought" : latest() ? `Thinking: ${latest()}` : "Thinking"}
when={props.completed} <Show when={props.completed && !expanded() && latest()}>: {latest()}</Show>
fallback={<Spinner color={theme.warning}>{latest() ? `Thinking: ${latest()}` : "Thinking"}</Spinner>} <Show when={props.completed && parts().length > 1}> · {parts().length} steps</Show>
> <Show when={props.completed && duration()}> · {Locale.duration(duration())}</Show>
<Show </InlineToolRow>
when={expanded()}
fallback={
<text fg={theme.warning} wrapMode="none">
+ Thought
<Show when={latest()}>: {latest()}</Show>
<Show when={parts().length > 1}> · {parts().length} steps</Show>
<Show when={duration()}> · {Locale.duration(duration())}</Show>
</text>
}
>
<text fg={theme.warning} wrapMode="none">
- Thought
<Show when={parts().length > 1}> · {parts().length} steps</Show>
<Show when={duration()}> · {Locale.duration(duration())}</Show>
</text>
</Show>
</Show>
</box>
<Show when={expanded()}> <Show when={expanded()}>
<For each={parts()}> <box paddingLeft={3}>
{(item) => { <For each={parts()}>
const content = createMemo(() => item.part.text.replace("[REDACTED]", "").trim()) {(item) => (
const summary = createMemo(() => reasoningSummary(content()))
const markdown = createMemo(() => {
if (!summary().title) return content()
if (!summary().body) return `**${summary().title}**`
return `**${summary().title}** · ${summary().body}`
})
return (
<box marginTop={1}> <box marginTop={1}>
<code <box
filetype="markdown" border={["left"]}
drawUnstyledText={false} customBorderChars={SplitBorder.customBorderChars}
streaming={false} borderColor={theme.backgroundElement}
syntaxStyle={syntax()} paddingLeft={1}
content={markdown()} >
conceal={ctx.markdownMode() === "rendered"} <code
fg={theme.textMuted} filetype="markdown"
/> drawUnstyledText={false}
streaming={false}
syntaxStyle={syntax()}
content={item.part.text.replace("[REDACTED]", "").trim()}
conceal={ctx.markdownMode() === "rendered"}
fg={theme.textMuted}
/>
</box>
</box> </box>
) )}
}} </For>
</For> </box>
</Show> </Show>
</box> </box>
</Show> </Show>
@@ -1814,27 +1810,41 @@ function ReasoningPart(props: {
return ( return (
<Show when={content()}> <Show when={content()}>
<box paddingLeft={3} flexDirection="column" flexShrink={0}> <box paddingLeft={3} flexDirection="column" flexShrink={0}>
<box onMouseUp={toggle}> <box
<ReasoningHeader border={!inMinimal() || expanded() ? ["left"] : undefined}
toggleable={inMinimal()} customBorderChars={SplitBorder.customBorderChars}
open={!inMinimal() || expanded()} borderColor={theme.backgroundElement}
done={isDone()} paddingLeft={!inMinimal() || expanded() ? 1 : 0}
title={summary().title} >
duration={isDone() ? Locale.duration(duration()) : undefined} <box onMouseUp={toggle}>
/> <ReasoningHeader
</box> toggleable={inMinimal()}
<Show when={(!inMinimal() || expanded()) && summary().body}> open={!inMinimal() || expanded()}
<box paddingLeft={inMinimal() ? 2 : 0} marginTop={1}> done={isDone()}
<code title={inMinimal() && !expanded() ? summary().title : null}
filetype="markdown" duration={isDone() ? Locale.duration(duration()) : undefined}
drawUnstyledText={false}
streaming={true}
syntaxStyle={syntax()}
content={summary().body}
conceal={ctx.markdownMode() === "rendered"}
fg={theme.textMuted}
/> />
</box> </box>
</box>
<Show when={!inMinimal() || expanded()}>
<box marginTop={1}>
<box
border={["left"]}
customBorderChars={SplitBorder.customBorderChars}
borderColor={theme.backgroundElement}
paddingLeft={inMinimal() ? 3 : 1}
>
<code
filetype="markdown"
drawUnstyledText={false}
streaming={true}
syntaxStyle={syntax()}
content={content()}
conceal={ctx.markdownMode() === "rendered"}
fg={theme.textMuted}
/>
</box>
</box>
</Show> </Show>
</box> </box>
</Show> </Show>