Skip to content

Commit f91baa8

Browse files
fix(overlay): add ESC key to dismiss overlay (#5598)
1 parent 574026c commit f91baa8

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

client-src/overlay.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -644,11 +644,34 @@ const createOverlay = (options) => {
644644
}, trustedTypesPolicyName);
645645
}
646646

647+
/** @type {(event: KeyboardEvent) => void} */
648+
let handleEscapeKey;
649+
650+
/**
651+
* @returns {void}
652+
*/
653+
654+
const hideOverlayWithEscCleanup = () => {
655+
window.removeEventListener("keydown", handleEscapeKey);
656+
hide();
657+
};
658+
647659
const overlayService = createOverlayMachine({
648660
showOverlay: ({ level = "error", messages, messageSource }) =>
649661
show(level, messages, options.trustedTypesPolicyName, messageSource),
650-
hideOverlay: hide,
662+
hideOverlay: hideOverlayWithEscCleanup,
651663
});
664+
/**
665+
* ESC key press to dismiss the overlay.
666+
* @param {KeyboardEvent} event Keydown event
667+
*/
668+
handleEscapeKey = (event) => {
669+
if (event.key === "Escape" || event.key === "Esc" || event.keyCode === 27) {
670+
overlayService.send({ type: "DISMISS" });
671+
}
672+
};
673+
674+
window.addEventListener("keydown", handleEscapeKey);
652675

653676
if (options.catchRuntimeError) {
654677
/**

test/client/ReactErrorBoundary.test.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,4 +232,41 @@ describe("createOverlay", () => {
232232
});
233233
showOverlayMock.mockRestore();
234234
});
235+
// ESC key test cases
236+
237+
it("should dismiss overlay when ESC key is pressed", () => {
238+
const options = { trustedTypesPolicyName: null, catchRuntimeError: true };
239+
const overlay = createOverlay(options);
240+
const showOverlayMock = jest.spyOn(overlay, "send");
241+
242+
const escEvent = new KeyboardEvent("keydown", { key: "Escape" });
243+
globalThis.window.dispatchEvent(escEvent);
244+
245+
expect(showOverlayMock).toHaveBeenCalledWith({ type: "DISMISS" });
246+
showOverlayMock.mockRestore();
247+
});
248+
249+
it("should dismiss overlay when 'Esc' key is pressed (older browsers)", () => {
250+
const options = { trustedTypesPolicyName: null, catchRuntimeError: true };
251+
const overlay = createOverlay(options);
252+
const showOverlayMock = jest.spyOn(overlay, "send");
253+
254+
const escEvent = new KeyboardEvent("keydown", { key: "Esc" });
255+
globalThis.window.dispatchEvent(escEvent);
256+
257+
expect(showOverlayMock).toHaveBeenCalledWith({ type: "DISMISS" });
258+
showOverlayMock.mockRestore();
259+
});
260+
261+
it("should not dismiss overlay for other keys", () => {
262+
const options = { trustedTypesPolicyName: null, catchRuntimeError: true };
263+
const overlay = createOverlay(options);
264+
const showOverlayMock = jest.spyOn(overlay, "send");
265+
266+
const otherKeyEvent = new KeyboardEvent("keydown", { key: "Enter" });
267+
globalThis.window.dispatchEvent(otherKeyEvent);
268+
269+
expect(showOverlayMock).not.toHaveBeenCalled();
270+
showOverlayMock.mockRestore();
271+
});
235272
});

0 commit comments

Comments
 (0)