Skip to content

Commit 367013f

Browse files
awschmederedelauna
andauthored
feat(webview): surface condense button and context progress bar in collapsed task header (#680)
* feat(webview): surface condense context button and progress bar in collapsed task header * feat(webview): replace FoldVertical with ListChevronsDownUp/ScissorsLineDashed, bump lucide-react to ^1.18.0 * fix(test): update SVG selector from lucide-fold-vertical to lucide-list-chevrons-down-up * feat(webview): surface condense context button and progress bar in collapsed task header * feat(webview): replace FoldVertical with ListChevronsDownUp/ScissorsLineDashed, bump lucide-react to ^1.18.0 * fix(test): update SVG selector from lucide-fold-vertical to lucide-list-chevrons-down-up * fix(webview): address PR review nits on collapsed task header - Remove .changeset entry (managed by maintainers, not agents) - Add stopPropagation guard to progress/condense container so clicking the progress bar cannot toggle the header on future refactors - Use ?? instead of || for maxTokens so a legitimate 0 is preserved - Assert condense click does not expand the header (regression guard) * fix(webview): use ?? for maxTokens in expanded task header --------- Co-authored-by: Elliott de Launay <edelauna@gmail.com> Co-authored-by: edelauna <54631123+edelauna@users.noreply.github.com>
1 parent 537cede commit 367013f

7 files changed

Lines changed: 42 additions & 30 deletions

File tree

pnpm-lock.yaml

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webview-ui/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
"i18next": "^25.0.0",
5151
"katex": "^0.16.11",
5252
"lru-cache": "^11.1.0",
53-
"lucide-react": "^0.577.0",
53+
"lucide-react": "^1.18.0",
5454
"mermaid": "^11.4.1",
5555
"posthog-js": "^1.227.2",
5656
"pretty-bytes": "^7.0.0",

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { memo, useRef, useState, useMemo } from "react"
22
import { useTranslation } from "react-i18next"
3-
import { ChevronUp, ChevronDown, HardDriveDownload, HardDriveUpload, FoldVertical, ArrowLeft } from "lucide-react"
3+
import { ChevronUp, ChevronDown, HardDriveDownload, HardDriveUpload, ListChevronsDownUp, ArrowLeft } from "lucide-react"
44
import prettyBytes from "pretty-bytes"
55

66
import type { ClineMessage } from "@roo-code/types"
@@ -82,7 +82,7 @@ const TaskHeader = ({
8282
const condenseButton = (
8383
<LucideIconButton
8484
title={t("chat:task.condenseContext")}
85-
icon={FoldVertical}
85+
icon={ListChevronsDownUp}
8686
disabled={buttonsDisabled}
8787
onClick={() => currentTaskItem && handleCondenseContext(currentTaskItem.id)}
8888
/>
@@ -275,6 +275,16 @@ const TaskHeader = ({
275275
</>
276276
)}
277277
</div>
278+
<div
279+
className="flex items-center gap-1 ml-8 w-60 min-w-[120px] shrink"
280+
onClick={(e) => e.stopPropagation()}>
281+
<ContextWindowProgress
282+
contextWindow={contextWindow}
283+
contextTokens={contextTokens || 0}
284+
maxTokens={maxTokens ?? undefined}
285+
/>
286+
{condenseButton}
287+
</div>
278288
</div>
279289
)}
280290
{/* Expanded state: Show task text and images */}
@@ -315,7 +325,7 @@ const TaskHeader = ({
315325
<ContextWindowProgress
316326
contextWindow={contextWindow}
317327
contextTokens={contextTokens || 0}
318-
maxTokens={maxTokens || undefined}
328+
maxTokens={maxTokens ?? undefined}
319329
/>
320330
{condenseButton}
321331
</div>

webview-ui/src/components/chat/__tests__/TaskHeader.spec.tsx

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -133,15 +133,22 @@ describe("TaskHeader", () => {
133133
expect(screen.queryByText(/\$/)).not.toBeInTheDocument()
134134
})
135135

136+
it("should render the condense context button in the collapsed state", () => {
137+
renderTaskHeader()
138+
// Button is visible without expanding the task header
139+
const buttons = screen.getAllByRole("button")
140+
const condenseButton = buttons.find((button) => button.querySelector("svg.lucide-list-chevrons-down-up"))
141+
expect(condenseButton).toBeDefined()
142+
expect(condenseButton?.querySelector("svg")).toBeInTheDocument()
143+
})
144+
136145
it("should render the condense context button when expanded", () => {
137146
renderTaskHeader()
138-
// First click to expand the task header
139147
const taskHeader = screen.getByText("Test task")
140148
fireEvent.click(taskHeader)
141149

142-
// Now find the condense button in the expanded state
143150
const buttons = screen.getAllByRole("button")
144-
const condenseButton = buttons.find((button) => button.querySelector("svg.lucide-fold-vertical"))
151+
const condenseButton = buttons.find((button) => button.querySelector("svg.lucide-list-chevrons-down-up"))
145152
expect(condenseButton).toBeDefined()
146153
expect(condenseButton?.querySelector("svg")).toBeInTheDocument()
147154
})
@@ -150,29 +157,24 @@ describe("TaskHeader", () => {
150157
const handleCondenseContext = vi.fn()
151158
renderTaskHeader({ handleCondenseContext })
152159

153-
// First click to expand the task header
154-
const taskHeader = screen.getByText("Test task")
155-
fireEvent.click(taskHeader)
156-
157-
// Find the button that contains the FoldVertical icon
160+
// Button is clickable in collapsed state without expanding first
158161
const buttons = screen.getAllByRole("button")
159-
const condenseButton = buttons.find((button) => button.querySelector("svg.lucide-fold-vertical"))
162+
const condenseButton = buttons.find((button) => button.querySelector("svg.lucide-list-chevrons-down-up"))
160163
expect(condenseButton).toBeDefined()
161164
fireEvent.click(condenseButton!)
162165
expect(handleCondenseContext).toHaveBeenCalledWith("test-task-id")
166+
// Clicking the condense button must not expand the header (stopPropagation guard).
167+
// The expanded state renders the "chat:task.title" label, which stays absent while collapsed.
168+
expect(screen.queryByText("chat:task.title")).not.toBeInTheDocument()
163169
})
164170

165171
it("should disable the condense context button when buttonsDisabled is true", () => {
166172
const handleCondenseContext = vi.fn()
167173
renderTaskHeader({ buttonsDisabled: true, handleCondenseContext })
168174

169-
// First click to expand the task header
170-
const taskHeader = screen.getByText("Test task")
171-
fireEvent.click(taskHeader)
172-
173-
// Find the button that contains the FoldVertical icon
175+
// Button is disabled in collapsed state without expanding first
174176
const buttons = screen.getAllByRole("button")
175-
const condenseButton = buttons.find((button) => button.querySelector("svg.lucide-fold-vertical"))
177+
const condenseButton = buttons.find((button) => button.querySelector("svg.lucide-list-chevrons-down-up"))
176178
expect(condenseButton).toBeDefined()
177179
expect(condenseButton).toBeDisabled()
178180
fireEvent.click(condenseButton!)

webview-ui/src/components/chat/context-management/CondensationResultRow.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useState } from "react"
22
import { useTranslation } from "react-i18next"
33
import { VSCodeBadge } from "@vscode/webview-ui-toolkit/react"
4-
import { FoldVertical } from "lucide-react"
4+
import { ListChevronsDownUp } from "lucide-react"
55

66
import type { ContextCondense } from "@roo-code/types"
77

@@ -32,7 +32,7 @@ export function CondensationResultRow({ data }: CondensationResultRowProps) {
3232
className="flex items-center justify-between cursor-pointer select-none"
3333
onClick={() => setIsExpanded(!isExpanded)}>
3434
<div className="flex items-center gap-2 flex-grow">
35-
<FoldVertical size={16} className="text-vscode-foreground" />
35+
<ListChevronsDownUp size={16} className="text-vscode-foreground" />
3636
<span className="font-bold text-vscode-foreground">
3737
{t("chat:contextManagement.condensation.title")}
3838
</span>

webview-ui/src/components/chat/context-management/TruncationResultRow.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useState } from "react"
22
import { useTranslation } from "react-i18next"
3-
import { FoldVertical } from "lucide-react"
3+
import { ScissorsLineDashed } from "lucide-react"
44

55
import type { ContextTruncation } from "@roo-code/types"
66

@@ -33,7 +33,7 @@ export function TruncationResultRow({ data }: TruncationResultRowProps) {
3333
className="flex items-center justify-between cursor-pointer select-none"
3434
onClick={() => setIsExpanded(!isExpanded)}>
3535
<div className="flex items-center gap-2 flex-grow">
36-
<FoldVertical size={16} className="text-vscode-foreground" />
36+
<ScissorsLineDashed size={16} className="text-vscode-foreground" />
3737
<span className="font-bold text-vscode-foreground">
3838
{t("chat:contextManagement.truncation.title")}
3939
</span>

webview-ui/src/components/settings/ContextManagementSettings.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { HTMLAttributes } from "react"
22
import React from "react"
33
import { useAppTranslation } from "@/i18n/TranslationContext"
44
import { VSCodeCheckbox, VSCodeTextArea } from "@vscode/webview-ui-toolkit/react"
5-
import { FoldVertical } from "lucide-react"
5+
import { ListChevronsDownUp } from "lucide-react"
66
import { DEFAULT_DIFF_FUZZY_THRESHOLD } from "@roo-code/types"
77

88
import { supportPrompt } from "@roo/support-prompt"
@@ -516,7 +516,7 @@ export const ContextManagementSettings = ({
516516
{autoCondenseContext && (
517517
<div className="flex flex-col gap-3 pl-3 border-l-2 border-vscode-button-background">
518518
<div className="flex items-center gap-4 font-bold">
519-
<FoldVertical size={16} />
519+
<ListChevronsDownUp size={16} />
520520
<div>{t("settings:contextManagement.condensingThreshold.label")}</div>
521521
</div>
522522
<div>

0 commit comments

Comments
 (0)