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
This commit is contained in:
Roo Code 2025-09-22 02:33:45 +00:00
parent ceb9d2b9f2
commit 28a6621a54

View file

@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from "react"
import { useTranslation } from "react-i18next"
import MarkdownBlock from "../common/MarkdownBlock"
import { Lightbulb } from "lucide-react"
import { Lightbulb, ChevronDown, ChevronUp } from "lucide-react"
interface ReasoningBlockProps {
content: string
@ -16,12 +16,14 @@ interface ReasoningBlockProps {
* Render reasoning with a heading and a simple timer.
* - Heading uses i18n key chat:reasoning.thinking
* - Timer runs while reasoning is active (no persistence)
* - Content can be toggled to show/hide
*/
export const ReasoningBlock = ({ content, isStreaming, isLast }: ReasoningBlockProps) => {
const { t } = useTranslation()
const startTimeRef = useRef<number>(Date.now())
const [elapsed, setElapsed] = useState<number>(0)
const [isCollapsed, setIsCollapsed] = useState<boolean>(false)
// Simple timer that runs while streaming
useEffect(() => {
@ -36,12 +38,24 @@ export const ReasoningBlock = ({ content, isStreaming, isLast }: ReasoningBlockP
const seconds = Math.floor(elapsed / 1000)
const secondsLabel = t("chat:reasoning.seconds", { count: seconds })
const handleToggle = (e: React.MouseEvent) => {
e.stopPropagation()
setIsCollapsed(!isCollapsed)
}
return (
<div>
<div className="flex items-center justify-between mb-2.5 pr-2">
<div className="flex items-center gap-2">
<div
className="flex items-center gap-2 cursor-pointer select-none hover:opacity-80"
onClick={handleToggle}>
<Lightbulb className="w-4" />
<span className="font-bold text-vscode-foreground">{t("chat:reasoning.thinking")}</span>
{isCollapsed ? (
<ChevronDown className="w-4 h-4 text-vscode-foreground opacity-60" />
) : (
<ChevronUp className="w-4 h-4 text-vscode-foreground opacity-60" />
)}
</div>
{elapsed > 0 && (
<span className="text-sm text-vscode-descriptionForeground tabular-nums flex items-center gap-1">
@ -49,7 +63,7 @@ export const ReasoningBlock = ({ content, isStreaming, isLast }: ReasoningBlockP
</span>
)}
</div>
{(content?.trim()?.length ?? 0) > 0 && (
{!isCollapsed && (content?.trim()?.length ?? 0) > 0 && (
<div className="border-l border-vscode-descriptionForeground/20 ml-2 pl-4 pb-1 text-vscode-descriptionForeground">
<MarkdownBlock markdown={content} />
</div>