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
This commit is contained in:
Merge Resolver 2025-08-19 17:55:09 -06:00
parent 782174edc5
commit e5b41c8ffc
2 changed files with 66 additions and 15 deletions

View file

@ -206,14 +206,16 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
display: "flex",
alignItems: "center",
gap: "6px",
}}>
}}
onClick={(e) => e.stopPropagation()}>
{allConfigs.map(({ key, icon, labelKey }) => {
const isEnabled = !!toggles[key]
return (
<StandardTooltip key={key} content={t(labelKey)}>
<span
<button
className={`codicon codicon-${icon}`}
data-active={isEnabled ? "true" : "false"}
onClick={() => onAutoApproveToggle(key, !isEnabled)}
style={{
fontSize: "14px",
flexShrink: 0,
@ -221,6 +223,19 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
color: isEnabled
? "var(--vscode-foreground)"
: "var(--vscode-descriptionForeground)",
background: "transparent",
border: "none",
cursor: "pointer",
padding: "2px",
borderRadius: "3px",
transition: "background-color 0.1s",
}}
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor =
"var(--vscode-toolbar-hoverBackground)"
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = "transparent"
}}
/>
</StandardTooltip>

View file

@ -243,12 +243,48 @@ describe("AutoApproveMenu", () => {
render(<AutoApproveMenu />)
const container = screen.getByText("Auto-approve").parentElement?.parentElement as HTMLElement
expect(container.querySelector(".codicon-eye")?.getAttribute("data-active")).toBe("true") // Read
expect(container.querySelector(".codicon-edit")?.getAttribute("data-active")).toBe("true") // Write
expect(container.querySelector(".codicon-terminal")?.getAttribute("data-active")).toBe("true") // Execute
expect(container.querySelector("button.codicon-eye")?.getAttribute("data-active")).toBe("true") // Read
expect(container.querySelector("button.codicon-edit")?.getAttribute("data-active")).toBe("true") // Write
expect(container.querySelector("button.codicon-terminal")?.getAttribute("data-active")).toBe("true") // Execute
})
it("should display tooltips on icons in collapsed view", async () => {
it("should toggle options when clicking icons in collapsed view", () => {
const mockSetAlwaysAllowReadOnly = vi.fn()
const mockSetAlwaysAllowWrite = vi.fn()
;(useExtensionState as ReturnType<typeof vi.fn>).mockReturnValue({
...defaultExtensionState,
autoApprovalEnabled: false,
alwaysAllowReadOnly: false,
alwaysAllowWrite: false,
setAlwaysAllowReadOnly: mockSetAlwaysAllowReadOnly,
setAlwaysAllowWrite: mockSetAlwaysAllowWrite,
})
render(<AutoApproveMenu />)
const container = screen.getByText("Auto-approve").parentElement?.parentElement as HTMLElement
const eyeButton = container.querySelector("button.codicon-eye") as HTMLElement
const editButton = container.querySelector("button.codicon-edit") as HTMLElement
// Click the read-only icon
fireEvent.click(eyeButton)
expect(mockPostMessage).toHaveBeenCalledWith({
type: "alwaysAllowReadOnly",
bool: true,
})
expect(mockSetAlwaysAllowReadOnly).toHaveBeenCalledWith(true)
// Click the write icon
fireEvent.click(editButton)
expect(mockPostMessage).toHaveBeenCalledWith({
type: "alwaysAllowWrite",
bool: true,
})
expect(mockSetAlwaysAllowWrite).toHaveBeenCalledWith(true)
})
it("should display tooltips on icon buttons in collapsed view", async () => {
const user = userEvent.setup()
;(useExtensionState as ReturnType<typeof vi.fn>).mockReturnValue({
@ -261,19 +297,19 @@ describe("AutoApproveMenu", () => {
render(<AutoApproveMenu />)
// Find the icons
// Find the icon buttons
const container = screen.getByText("Auto-approve").parentElement?.parentElement
const eyeIcon = container?.querySelector(".codicon-eye") as HTMLElement
const editIcon = container?.querySelector(".codicon-edit") as HTMLElement
const terminalIcon = container?.querySelector(".codicon-terminal") as HTMLElement
const eyeButton = container?.querySelector("button.codicon-eye") as HTMLElement
const editButton = container?.querySelector("button.codicon-edit") as HTMLElement
const terminalButton = container?.querySelector("button.codicon-terminal") as HTMLElement
// Verify icons are present
expect(eyeIcon).toBeInTheDocument()
expect(editIcon).toBeInTheDocument()
expect(terminalIcon).toBeInTheDocument()
// Verify icon buttons are present
expect(eyeButton).toBeInTheDocument()
expect(editButton).toBeInTheDocument()
expect(terminalButton).toBeInTheDocument()
// Test read-only icon tooltip
await user.hover(eyeIcon)
await user.hover(eyeButton)
await waitFor(() => {
expect(screen.getByRole("tooltip")).toHaveTextContent("Read-only operations")
})