Skip to content

Commit c6e8b04

Browse files
authored
feat: Enhance HistoryPreview component with collapsible/expandable ta… (RooCodeInc#3534)
* feat: Enhance HistoryPreview component with collapsible/expandable task history view * fix: Update font size for empty state/'No recent tasks' message in HistoryPreview component
1 parent c0b3c69 commit c6e8b04

File tree

2 files changed

+132
-86
lines changed

2 files changed

+132
-86
lines changed

.changeset/cold-dingos-run.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"claude-dev": minor
3+
---
4+
5+
Recent task list is now collapsible, allowing users to hide their recent tasks (e.g. when sharing their screen).

webview-ui/src/components/history/HistoryPreview.tsx

Lines changed: 127 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
22
import { useExtensionState } from "@/context/ExtensionStateContext"
33
import { vscode } from "@/utils/vscode"
4-
import { memo } from "react"
4+
import { memo, useState } from "react"
55
import { TaskServiceClient } from "@/services/grpc-client"
66
import { formatLargeNumber } from "@/utils/format"
77

@@ -11,10 +11,16 @@ type HistoryPreviewProps = {
1111

1212
const HistoryPreview = ({ showHistoryView }: HistoryPreviewProps) => {
1313
const { taskHistory } = useExtensionState()
14+
const [isExpanded, setIsExpanded] = useState(true)
15+
1416
const handleHistorySelect = (id: string) => {
1517
TaskServiceClient.showTaskWithId({ value: id }).catch((error) => console.error("Error showing task:", error))
1618
}
1719

20+
const toggleExpanded = () => {
21+
setIsExpanded(!isExpanded)
22+
}
23+
1824
const formatDate = (timestamp: number) => {
1925
const date = new Date(timestamp)
2026
return date
@@ -48,16 +54,31 @@ const HistoryPreview = ({ showHistoryView }: HistoryPreviewProps) => {
4854
opacity: 1;
4955
pointer-events: auto;
5056
}
57+
.history-header {
58+
cursor: pointer;
59+
user-select: none;
60+
}
61+
.history-header:hover {
62+
opacity: 0.8;
63+
}
5164
`}
5265
</style>
5366

5467
<div
68+
className="history-header"
69+
onClick={toggleExpanded}
5570
style={{
5671
color: "var(--vscode-descriptionForeground)",
5772
margin: "10px 20px 10px 20px",
5873
display: "flex",
5974
alignItems: "center",
6075
}}>
76+
<span
77+
className={`codicon codicon-chevron-${isExpanded ? "down" : "right"}`}
78+
style={{
79+
marginRight: "4px",
80+
transform: "scale(0.9)",
81+
}}></span>
6182
<span
6283
className="codicon codicon-comment-discussion"
6384
style={{
@@ -74,102 +95,122 @@ const HistoryPreview = ({ showHistoryView }: HistoryPreviewProps) => {
7495
</span>
7596
</div>
7697

77-
<div style={{ padding: "0px 20px 0 20px" }}>
78-
{taskHistory
79-
.filter((item) => item.ts && item.task)
80-
.slice(0, 3)
81-
.map((item) => (
82-
<div key={item.id} className="history-preview-item" onClick={() => handleHistorySelect(item.id)}>
83-
<div style={{ padding: "12px" }}>
84-
<div style={{ marginBottom: "8px" }}>
85-
<span
86-
style={{
87-
color: "var(--vscode-descriptionForeground)",
88-
fontWeight: 500,
89-
fontSize: "0.85em",
90-
textTransform: "uppercase",
91-
}}>
92-
{formatDate(item.ts)}
93-
</span>
94-
</div>
95-
{item.isFavorited && (
98+
{isExpanded && (
99+
<div style={{ padding: "0px 20px 0 20px" }}>
100+
{taskHistory.filter((item) => item.ts && item.task).length > 0 ? (
101+
<>
102+
{taskHistory
103+
.filter((item) => item.ts && item.task)
104+
.slice(0, 3)
105+
.map((item) => (
96106
<div
97-
style={{
98-
position: "absolute",
99-
top: "12px",
100-
right: "12px",
101-
color: "var(--vscode-button-background)",
102-
}}>
103-
<span className="codicon codicon-star-full" aria-label="Favorited" />
104-
</div>
105-
)}
107+
key={item.id}
108+
className="history-preview-item"
109+
onClick={() => handleHistorySelect(item.id)}>
110+
<div style={{ padding: "12px" }}>
111+
<div style={{ marginBottom: "8px" }}>
112+
<span
113+
style={{
114+
color: "var(--vscode-descriptionForeground)",
115+
fontWeight: 500,
116+
fontSize: "0.85em",
117+
textTransform: "uppercase",
118+
}}>
119+
{formatDate(item.ts)}
120+
</span>
121+
</div>
122+
{item.isFavorited && (
123+
<div
124+
style={{
125+
position: "absolute",
126+
top: "12px",
127+
right: "12px",
128+
color: "var(--vscode-button-background)",
129+
}}>
130+
<span className="codicon codicon-star-full" aria-label="Favorited" />
131+
</div>
132+
)}
106133

107-
<div
108-
id={`history-preview-task-${item.id}`}
109-
className="history-preview-task"
110-
style={{
111-
fontSize: "var(--vscode-font-size)",
112-
color: "var(--vscode-descriptionForeground)",
113-
marginBottom: "8px",
114-
display: "-webkit-box",
115-
WebkitLineClamp: 3,
116-
WebkitBoxOrient: "vertical",
117-
overflow: "hidden",
118-
whiteSpace: "pre-wrap",
119-
wordBreak: "break-word",
120-
overflowWrap: "anywhere",
121-
}}>
122-
<span className="ph-no-capture">{item.task}</span>
123-
</div>
124-
<div
134+
<div
135+
id={`history-preview-task-${item.id}`}
136+
className="history-preview-task"
137+
style={{
138+
fontSize: "var(--vscode-font-size)",
139+
color: "var(--vscode-descriptionForeground)",
140+
marginBottom: "8px",
141+
display: "-webkit-box",
142+
WebkitLineClamp: 3,
143+
WebkitBoxOrient: "vertical",
144+
overflow: "hidden",
145+
whiteSpace: "pre-wrap",
146+
wordBreak: "break-word",
147+
overflowWrap: "anywhere",
148+
}}>
149+
<span className="ph-no-capture">{item.task}</span>
150+
</div>
151+
<div
152+
style={{
153+
fontSize: "0.85em",
154+
color: "var(--vscode-descriptionForeground)",
155+
}}>
156+
<span>
157+
Tokens: ↑{formatLargeNumber(item.tokensIn || 0)}
158+
{formatLargeNumber(item.tokensOut || 0)}
159+
</span>
160+
{!!item.cacheWrites && (
161+
<>
162+
{" • "}
163+
<span>
164+
Cache: +{formatLargeNumber(item.cacheWrites || 0)}{" "}
165+
{formatLargeNumber(item.cacheReads || 0)}
166+
</span>
167+
</>
168+
)}
169+
{!!item.totalCost && (
170+
<>
171+
{" • "}
172+
<span>API Cost: ${item.totalCost?.toFixed(4)}</span>
173+
</>
174+
)}
175+
</div>
176+
</div>
177+
</div>
178+
))}
179+
<div
180+
style={{
181+
display: "flex",
182+
alignItems: "center",
183+
justifyContent: "center",
184+
}}>
185+
<VSCodeButton
186+
appearance="icon"
187+
onClick={() => showHistoryView()}
125188
style={{
126-
fontSize: "0.85em",
127-
color: "var(--vscode-descriptionForeground)",
189+
opacity: 0.9,
128190
}}>
129-
<span>
130-
Tokens: ↑{formatLargeNumber(item.tokensIn || 0)}{formatLargeNumber(item.tokensOut || 0)}
131-
</span>
132-
{!!item.cacheWrites && (
133-
<>
134-
{" • "}
135-
<span>
136-
Cache: +{formatLargeNumber(item.cacheWrites || 0)}{" "}
137-
{formatLargeNumber(item.cacheReads || 0)}
138-
</span>
139-
</>
140-
)}
141-
{!!item.totalCost && (
142-
<>
143-
{" • "}
144-
<span>API Cost: ${item.totalCost?.toFixed(4)}</span>
145-
</>
146-
)}
147-
</div>
191+
<div
192+
style={{
193+
fontSize: "var(--vscode-font-size)",
194+
color: "var(--vscode-descriptionForeground)",
195+
}}>
196+
View all history
197+
</div>
198+
</VSCodeButton>
148199
</div>
149-
</div>
150-
))}
151-
<div
152-
style={{
153-
display: "flex",
154-
alignItems: "center",
155-
justifyContent: "center",
156-
}}>
157-
<VSCodeButton
158-
appearance="icon"
159-
onClick={() => showHistoryView()}
160-
style={{
161-
opacity: 0.9,
162-
}}>
200+
</>
201+
) : (
163202
<div
164203
style={{
165-
fontSize: "var(--vscode-font-size)",
204+
textAlign: "center",
166205
color: "var(--vscode-descriptionForeground)",
206+
fontSize: "var(--vscode-font-size)",
207+
padding: "10px 0",
167208
}}>
168-
View all history
209+
No recent tasks
169210
</div>
170-
</VSCodeButton>
211+
)}
171212
</div>
172-
</div>
213+
)}
173214
</div>
174215
)
175216
}

0 commit comments

Comments
 (0)