From 643a3657d5a38ceb8bec277c9a3fb6c685f79c73 Mon Sep 17 00:00:00 2001 From: Lukas Boehler Date: Mon, 2 Nov 2026 07:38:14 +0100 Subject: [PATCH] fix(a11y): keyboard-operable launcher The launcher is a focusable role=button with a name and aria-expanded; Enter and Space open it and move focus into the messenger, a visible focus ring shows on keyboard focus, and closing the messenger from inside returns focus to it. Co-Authored-By: Claude Opus 5.5 --- src/GleapFeedbackButtonManager.js | 35 ++++++++++++++++++++++++++++++- src/GleapFrameManager.js | 19 +++++++++++++++++ src/UI.js | 10 +++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/GleapFeedbackButtonManager.js b/src/GleapFeedbackButtonManager.js index 9cac4e51..f7694192 100644 --- a/src/GleapFeedbackButtonManager.js +++ b/src/GleapFeedbackButtonManager.js @@ -84,7 +84,7 @@ export default class GleapFeedbackButtonManager { } } - feedbackButtonPressed() { + feedbackButtonPressed(fromKeyboard = false) { var frameManager = GleapFrameManager.getInstance(); if (frameManager.isOpened()) { frameManager.hideWidget(); @@ -93,7 +93,24 @@ export default class GleapFeedbackButtonManager { frameManager.setAppMode('widget'); frameManager.showWidget(); this.updateRedDot(false); + // Opened from the keyboard: the keyboard moves into the messenger with it. + if (fromKeyboard) { + frameManager.focusFrame(); + } + } + } + + /** + * The messenger closed while the keyboard was in it (Escape, its close button): the keyboard + * comes back to the launcher instead of the top of the page. + */ + restoreFocus() { + if (!this.feedbackButton || !this.feedbackButton.isConnected) { + return; } + try { + this.feedbackButton.focus({ preventScroll: true }); + } catch (e) {} } /** @@ -105,10 +122,20 @@ export default class GleapFeedbackButtonManager { } this.injectedFeedbackButton = true; + // A div (a