tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit ea8e66f2a395cfce142b15a9c015fb4dca6a2a68
parent 7374c542014937ba08c1df36cf4b17abdad25379
Author: Mark Striemer <mstriemer@mozilla.com>
Date:   Fri, 24 Oct 2025 15:28:18 +0000

Bug 1981715 - moz-button keyboard support for PanelMultiView r=daleharvey,desktop-theme-reviewers,hjones

Differential Revision: https://phabricator.services.mozilla.com/D269429

Diffstat:
Mbrowser/base/content/browser-trustPanel.js | 1+
Mbrowser/components/customizableui/PanelMultiView.sys.mjs | 9++++++++-
Mbrowser/components/customizableui/test/browser_PanelMultiView_keyboard.js | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mbrowser/themes/shared/controlcenter/panel.css | 2+-
4 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/browser/base/content/browser-trustPanel.js b/browser/base/content/browser-trustPanel.js @@ -499,6 +499,7 @@ class TrustPanel { let children = blockers.map(async blocker => { let button = document.createElement("moz-button"); + button.classList.add("moz-button-subviewbutton-nav"); button.setAttribute("iconsrc", blocker.iconSrc); button.setAttribute("type", "ghost icon"); document.l10n.setAttributes( diff --git a/browser/components/customizableui/PanelMultiView.sys.mjs b/browser/components/customizableui/PanelMultiView.sys.mjs @@ -1594,6 +1594,7 @@ export var PanelView = class extends AssociatedToNode { localName == "toolbarbutton" || localName == "checkbox" || localName == "a" || + localName == "moz-button" || localName == "moz-toggle" || node.classList.contains("text-link") || (!arrowKey && isNavigableWithTabOnly) || @@ -1884,7 +1885,13 @@ export var PanelView = class extends AssociatedToNode { // If the current button is _not_ one that points to a subview, pressing // the arrow key shouldn't do anything. let button = this.selectedElement; - if (!button || !button.classList.contains("subviewbutton-nav")) { + if ( + !button || + !( + button.classList.contains("subviewbutton-nav") || + button.classList.contains("moz-button-subviewbutton-nav") + ) + ) { break; } } diff --git a/browser/components/customizableui/test/browser_PanelMultiView_keyboard.js b/browser/components/customizableui/test/browser_PanelMultiView_keyboard.js @@ -34,6 +34,8 @@ let gBrowserBrowser; let gIframeView; let gIframeIframe; let gToggle; +let gMozButton; +let gMozButtonSubviewNav; let gComponentView; let gShadowRoot; let gShadowRootButtonA; @@ -157,6 +159,15 @@ add_setup(async function () { gToggle = document.createElement("moz-toggle"); gToggle.label = "Test label"; gMainView.appendChild(gToggle); + gMozButton = document.createElement("moz-button"); + gMozButton.label = "gMozButton"; + gMozButton.id = "gMozButton"; + gMainView.appendChild(gMozButton); + gMozButtonSubviewNav = document.createElement("moz-button"); + gMozButtonSubviewNav.label = "gMozButtonSubviewNav"; + gMozButtonSubviewNav.id = "gMozButtonSubviewNav"; + gMozButtonSubviewNav.classList.add("moz-button-subviewbutton-nav"); + gMainView.appendChild(gMozButtonSubviewNav); gMainTabOrder = [ gMainButton1, @@ -169,6 +180,8 @@ add_setup(async function () { gNamespacedLink, gLink, gToggle, + gMozButton, + gMozButtonSubviewNav, ]; gMainArrowOrder = [ gMainButton1, @@ -178,6 +191,8 @@ add_setup(async function () { gNamespacedLink, gLink, gToggle, + gMozButton, + gMozButtonSubviewNav, ]; gSubView = document.createXULElement("panelview"); @@ -447,6 +462,48 @@ add_task(async function testLeftArrowTextarea() { await hidePopup(); }); +add_task(async function testRightArrow() { + await openPopup(); + + // Ensure non moz-button-subviewbutton-navs respond to the right arrow + let clicked = false; + let assertNoClick = () => { + clicked = true; + }; + gMozButton.addEventListener("click", assertNoClick); + // Focus using the arrow keys so PanelMultiView#selectedElement is set + for (let i = 0; i < gMainTabOrder.length; i++) { + EventUtils.synthesizeKey("KEY_ArrowUp"); + if (document.activeElement == gMozButton) { + break; + } + } + is(document.activeElement, gMozButton, "gMozButton focused"); + EventUtils.synthesizeKey("KEY_ArrowRight"); + ok(!clicked, "click handler should not be triggered for regular button"); + EventUtils.synthesizeKey(" "); + ok(clicked, "click handler triggered on space"); + gMozButton.removeEventListener("click", assertNoClick); + + // Ensure moz-button-subviewbutton-nav gets click on right arrow + gMozButtonSubviewNav.addEventListener( + "click", + () => gPanelMultiView.showSubView(gSubView, gMozButtonSubviewNav), + { once: true } + ); + let shown = BrowserTestUtils.waitForEvent(gSubView, "ViewShown"); + EventUtils.synthesizeKey("KEY_ArrowDown"); + is( + document.activeElement, + gMozButtonSubviewNav, + "gMozButtonSubviewNav focused" + ); + EventUtils.synthesizeKey("KEY_ArrowRight"); + await shown; + ok(true, "Triggered moz-button-subviewbutton-nav on right arrow"); + await hidePopup(); +}); + // Test navigation to a button which is initially disabled and later enabled. add_task(async function testDynamicButton() { gMainButton2.disabled = true; diff --git a/browser/themes/shared/controlcenter/panel.css b/browser/themes/shared/controlcenter/panel.css @@ -968,7 +968,7 @@ } } -#trustpanel-blockerView moz-button { +.moz-button-subviewbutton-nav { --button-font-weight: normal; --button-alignment: inline-start; --button-border-radius: var(--border-radius-small);