Skip to content

Commit e5b41c8

Browse files
author
Merge Resolver
committed
feat: make collapsed auto-approve icons clickable to toggle options directly
- Icons in collapsed view are now clickable buttons that toggle their respective options - Added hover effect for better UX feedback - Clicking an icon directly toggles the auto-approve option without expanding the menu - Updated tests to verify the new clickable behavior - Maintains tooltips on all icon buttons
1 parent 782174e commit e5b41c8

File tree

2 files changed

+66
-15
lines changed

2 files changed

+66
-15
lines changed

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,21 +206,36 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
206206
display: "flex",
207207
alignItems: "center",
208208
gap: "6px",
209-
}}>
209+
}}
210+
onClick={(e) => e.stopPropagation()}>
210211
{allConfigs.map(({ key, icon, labelKey }) => {
211212
const isEnabled = !!toggles[key]
212213
return (
213214
<StandardTooltip key={key} content={t(labelKey)}>
214-
<span
215+
<button
215216
className={`codicon codicon-${icon}`}
216217
data-active={isEnabled ? "true" : "false"}
218+
onClick={() => onAutoApproveToggle(key, !isEnabled)}
217219
style={{
218220
fontSize: "14px",
219221
flexShrink: 0,
220222
opacity: isEnabled ? 1 : 0.5,
221223
color: isEnabled
222224
? "var(--vscode-foreground)"
223225
: "var(--vscode-descriptionForeground)",
226+
background: "transparent",
227+
border: "none",
228+
cursor: "pointer",
229+
padding: "2px",
230+
borderRadius: "3px",
231+
transition: "background-color 0.1s",
232+
}}
233+
onMouseEnter={(e) => {
234+
e.currentTarget.style.backgroundColor =
235+
"var(--vscode-toolbar-hoverBackground)"
236+
}}
237+
onMouseLeave={(e) => {
238+
e.currentTarget.style.backgroundColor = "transparent"
224239
}}
225240
/>
226241
</StandardTooltip>

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

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -243,12 +243,48 @@ describe("AutoApproveMenu", () => {
243243
render(<AutoApproveMenu />)
244244

245245
const container = screen.getByText("Auto-approve").parentElement?.parentElement as HTMLElement
246-
expect(container.querySelector(".codicon-eye")?.getAttribute("data-active")).toBe("true") // Read
247-
expect(container.querySelector(".codicon-edit")?.getAttribute("data-active")).toBe("true") // Write
248-
expect(container.querySelector(".codicon-terminal")?.getAttribute("data-active")).toBe("true") // Execute
246+
expect(container.querySelector("button.codicon-eye")?.getAttribute("data-active")).toBe("true") // Read
247+
expect(container.querySelector("button.codicon-edit")?.getAttribute("data-active")).toBe("true") // Write
248+
expect(container.querySelector("button.codicon-terminal")?.getAttribute("data-active")).toBe("true") // Execute
249249
})
250250

251-
it("should display tooltips on icons in collapsed view", async () => {
251+
it("should toggle options when clicking icons in collapsed view", () => {
252+
const mockSetAlwaysAllowReadOnly = vi.fn()
253+
const mockSetAlwaysAllowWrite = vi.fn()
254+
255+
;(useExtensionState as ReturnType<typeof vi.fn>).mockReturnValue({
256+
...defaultExtensionState,
257+
autoApprovalEnabled: false,
258+
alwaysAllowReadOnly: false,
259+
alwaysAllowWrite: false,
260+
setAlwaysAllowReadOnly: mockSetAlwaysAllowReadOnly,
261+
setAlwaysAllowWrite: mockSetAlwaysAllowWrite,
262+
})
263+
264+
render(<AutoApproveMenu />)
265+
266+
const container = screen.getByText("Auto-approve").parentElement?.parentElement as HTMLElement
267+
const eyeButton = container.querySelector("button.codicon-eye") as HTMLElement
268+
const editButton = container.querySelector("button.codicon-edit") as HTMLElement
269+
270+
// Click the read-only icon
271+
fireEvent.click(eyeButton)
272+
expect(mockPostMessage).toHaveBeenCalledWith({
273+
type: "alwaysAllowReadOnly",
274+
bool: true,
275+
})
276+
expect(mockSetAlwaysAllowReadOnly).toHaveBeenCalledWith(true)
277+
278+
// Click the write icon
279+
fireEvent.click(editButton)
280+
expect(mockPostMessage).toHaveBeenCalledWith({
281+
type: "alwaysAllowWrite",
282+
bool: true,
283+
})
284+
expect(mockSetAlwaysAllowWrite).toHaveBeenCalledWith(true)
285+
})
286+
287+
it("should display tooltips on icon buttons in collapsed view", async () => {
252288
const user = userEvent.setup()
253289

254290
;(useExtensionState as ReturnType<typeof vi.fn>).mockReturnValue({
@@ -261,19 +297,19 @@ describe("AutoApproveMenu", () => {
261297

262298
render(<AutoApproveMenu />)
263299

264-
// Find the icons
300+
// Find the icon buttons
265301
const container = screen.getByText("Auto-approve").parentElement?.parentElement
266-
const eyeIcon = container?.querySelector(".codicon-eye") as HTMLElement
267-
const editIcon = container?.querySelector(".codicon-edit") as HTMLElement
268-
const terminalIcon = container?.querySelector(".codicon-terminal") as HTMLElement
302+
const eyeButton = container?.querySelector("button.codicon-eye") as HTMLElement
303+
const editButton = container?.querySelector("button.codicon-edit") as HTMLElement
304+
const terminalButton = container?.querySelector("button.codicon-terminal") as HTMLElement
269305

270-
// Verify icons are present
271-
expect(eyeIcon).toBeInTheDocument()
272-
expect(editIcon).toBeInTheDocument()
273-
expect(terminalIcon).toBeInTheDocument()
306+
// Verify icon buttons are present
307+
expect(eyeButton).toBeInTheDocument()
308+
expect(editButton).toBeInTheDocument()
309+
expect(terminalButton).toBeInTheDocument()
274310

275311
// Test read-only icon tooltip
276-
await user.hover(eyeIcon)
312+
await user.hover(eyeButton)
277313
await waitFor(() => {
278314
expect(screen.getByRole("tooltip")).toHaveTextContent("Read-only operations")
279315
})

0 commit comments

Comments
 (0)