Skip to content

Commit e3a8e03

Browse files
roomote[bot]roomotedaniel-lxs
authored
feat: add ESC key handling for modes, API provider, and indexing settings popovers (RooCodeInc#6175)
Co-authored-by: Roo Code <[email protected]> Co-authored-by: Daniel Riccio <[email protected]>
1 parent 41aaf07 commit e3a8e03

File tree

9 files changed

+324
-381
lines changed

9 files changed

+324
-381
lines changed

webview-ui/src/__tests__/SearchableSelect.spec.tsx

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,4 +253,67 @@ describe("SearchableSelect", () => {
253253
expect(within(dropdown).queryByText("Option 3")).not.toBeInTheDocument()
254254
})
255255
})
256+
257+
it("closes the dropdown when ESC key is pressed", async () => {
258+
const user = userEvent.setup()
259+
render(<SearchableSelect {...defaultProps} />)
260+
261+
// Open the dropdown
262+
const trigger = screen.getByRole("combobox")
263+
await user.click(trigger)
264+
265+
// Verify dropdown is open
266+
expect(trigger).toHaveAttribute("aria-expanded", "true")
267+
expect(screen.getByRole("listbox")).toBeInTheDocument()
268+
269+
// Press ESC key
270+
fireEvent.keyDown(window, { key: "Escape" })
271+
272+
// Verify dropdown is closed
273+
await waitFor(() => {
274+
expect(trigger).toHaveAttribute("aria-expanded", "false")
275+
expect(screen.queryByRole("listbox")).not.toBeInTheDocument()
276+
})
277+
})
278+
279+
it("does not close the dropdown when ESC is pressed while dropdown is closed", async () => {
280+
render(<SearchableSelect {...defaultProps} />)
281+
282+
const trigger = screen.getByRole("combobox")
283+
284+
// Ensure dropdown is closed
285+
expect(trigger).toHaveAttribute("aria-expanded", "false")
286+
287+
// Press ESC key
288+
fireEvent.keyDown(window, { key: "Escape" })
289+
290+
// Verify dropdown remains closed
291+
expect(trigger).toHaveAttribute("aria-expanded", "false")
292+
expect(screen.queryByRole("listbox")).not.toBeInTheDocument()
293+
})
294+
295+
it("prevents default and stops propagation when ESC is pressed", async () => {
296+
const user = userEvent.setup()
297+
render(<SearchableSelect {...defaultProps} />)
298+
299+
// Open the dropdown
300+
const trigger = screen.getByRole("combobox")
301+
await user.click(trigger)
302+
303+
// Create a mock event to track preventDefault and stopPropagation
304+
const escapeEvent = new KeyboardEvent("keydown", {
305+
key: "Escape",
306+
bubbles: true,
307+
cancelable: true,
308+
})
309+
const preventDefaultSpy = vi.spyOn(escapeEvent, "preventDefault")
310+
const stopPropagationSpy = vi.spyOn(escapeEvent, "stopPropagation")
311+
312+
// Dispatch the event
313+
window.dispatchEvent(escapeEvent)
314+
315+
// Verify preventDefault and stopPropagation were called
316+
expect(preventDefaultSpy).toHaveBeenCalled()
317+
expect(stopPropagationSpy).toHaveBeenCalled()
318+
})
256319
})

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {
3838
} from "@src/components/ui"
3939
import { AlertTriangle } from "lucide-react"
4040
import { useRooPortal } from "@src/components/ui/hooks/useRooPortal"
41+
import { useEscapeKey } from "@src/hooks/useEscapeKey"
4142
import type { EmbedderProvider } from "@roo/embeddingModels"
4243
import type { IndexingStatus } from "@roo/ExtensionMessage"
4344
import { CODEBASE_INDEX_DEFAULTS } from "@roo-code/types"
@@ -440,6 +441,9 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
440441
})
441442
}, [checkUnsavedChanges])
442443

444+
// Use the shared ESC key handler hook - respects unsaved changes logic
445+
useEscapeKey(open, handlePopoverClose)
446+
443447
const handleSaveSettings = () => {
444448
// Validate settings before saving
445449
if (!validateSettings()) {

0 commit comments

Comments
 (0)