Skip to content

Commit 28a6621

Browse files
committed
feat: add toggle button to show/hide thinking output
- Added collapsible state to ReasoningBlock component - Implemented ChevronDown/ChevronUp icons for visual feedback - Made thinking content toggleable with click interaction - Maintains timer display while collapsed Fixes #8209
1 parent ceb9d2b commit 28a6621

File tree

1 file changed

+17
-3
lines changed

1 file changed

+17
-3
lines changed

webview-ui/src/components/chat/ReasoningBlock.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from "react"
22
import { useTranslation } from "react-i18next"
33

44
import MarkdownBlock from "../common/MarkdownBlock"
5-
import { Lightbulb } from "lucide-react"
5+
import { Lightbulb, ChevronDown, ChevronUp } from "lucide-react"
66

77
interface ReasoningBlockProps {
88
content: string
@@ -16,12 +16,14 @@ interface ReasoningBlockProps {
1616
* Render reasoning with a heading and a simple timer.
1717
* - Heading uses i18n key chat:reasoning.thinking
1818
* - Timer runs while reasoning is active (no persistence)
19+
* - Content can be toggled to show/hide
1920
*/
2021
export const ReasoningBlock = ({ content, isStreaming, isLast }: ReasoningBlockProps) => {
2122
const { t } = useTranslation()
2223

2324
const startTimeRef = useRef<number>(Date.now())
2425
const [elapsed, setElapsed] = useState<number>(0)
26+
const [isCollapsed, setIsCollapsed] = useState<boolean>(false)
2527

2628
// Simple timer that runs while streaming
2729
useEffect(() => {
@@ -36,20 +38,32 @@ export const ReasoningBlock = ({ content, isStreaming, isLast }: ReasoningBlockP
3638
const seconds = Math.floor(elapsed / 1000)
3739
const secondsLabel = t("chat:reasoning.seconds", { count: seconds })
3840

41+
const handleToggle = (e: React.MouseEvent) => {
42+
e.stopPropagation()
43+
setIsCollapsed(!isCollapsed)
44+
}
45+
3946
return (
4047
<div>
4148
<div className="flex items-center justify-between mb-2.5 pr-2">
42-
<div className="flex items-center gap-2">
49+
<div
50+
className="flex items-center gap-2 cursor-pointer select-none hover:opacity-80"
51+
onClick={handleToggle}>
4352
<Lightbulb className="w-4" />
4453
<span className="font-bold text-vscode-foreground">{t("chat:reasoning.thinking")}</span>
54+
{isCollapsed ? (
55+
<ChevronDown className="w-4 h-4 text-vscode-foreground opacity-60" />
56+
) : (
57+
<ChevronUp className="w-4 h-4 text-vscode-foreground opacity-60" />
58+
)}
4559
</div>
4660
{elapsed > 0 && (
4761
<span className="text-sm text-vscode-descriptionForeground tabular-nums flex items-center gap-1">
4862
{secondsLabel}
4963
</span>
5064
)}
5165
</div>
52-
{(content?.trim()?.length ?? 0) > 0 && (
66+
{!isCollapsed && (content?.trim()?.length ?? 0) > 0 && (
5367
<div className="border-l border-vscode-descriptionForeground/20 ml-2 pl-4 pb-1 text-vscode-descriptionForeground">
5468
<MarkdownBlock markdown={content} />
5569
</div>

0 commit comments

Comments
 (0)