Bug 1377273 - Added focus styling for onboarding overlay button. r=mossop, r=gasolin, a=lizzard
☠☠ backed out by c8da3a874d4a ☠ ☠
authorYura Zenevich <yura.zenevich@gmail.com>
Fri, 28 Jul 2017 14:27:43 -0400
changeset 423692 db1c6a7e5ec638eb15a233faccb17f5007bf66f5
parent 423691 e3c51a9aa108081c96ad8d5a993e6c513b00e84e
child 423693 ccdd5c4ad925466c442a62d0ca4c3d2baf9bde29
push id1517
push userjlorenzo@mozilla.com
push dateThu, 14 Sep 2017 16:50:54 +0000
treeherdermozilla-release@3b41fd564418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmossop, gasolin, lizzard
bugs1377273
milestone56.0
Bug 1377273 - Added focus styling for onboarding overlay button. r=mossop, r=gasolin, a=lizzard MozReview-Commit-ID: BZgx4ODL2at
browser/extensions/onboarding/content/onboarding.css
browser/extensions/onboarding/content/onboarding.js
browser/extensions/onboarding/test/browser/browser.ini
browser/extensions/onboarding/test/browser/browser_onboarding_accessibility.js
--- a/browser/extensions/onboarding/content/onboarding.css
+++ b/browser/extensions/onboarding/content/onboarding.css
@@ -29,16 +29,24 @@
   cursor: pointer;
   top: 34px;
   offset-inline-start: 34px;
   border: none;
   /* Set to none so no grey contrast background in the high-contrast mode */
   background: none;
 }
 
+/* Keyboard focus styling */
+#onboarding-overlay-button:-moz-focusring {
+  outline: solid 2px rgba(0, 0, 0, 0.1);
+  -moz-outline-radius: 5px;
+  outline-offset: 5px;
+  transition: outline-offset 150ms;
+}
+
 #onboarding-overlay-button-icon {
   width: 36px;
   vertical-align: top;
 }
 
 #onboarding-notification-icon::after,
 #onboarding-overlay-button::after {
   background: #5ce6e6;
@@ -306,17 +314,18 @@
   border-radius: 0;
   color: #fff;
   float: inline-end;
   margin-inline-end: 26px;
   margin-top: -32px;
 }
 
 /* Remove default dotted outline around buttons' text */
-.onboarding-tour-action-button::-moz-focus-inner {
+.onboarding-tour-action-button::-moz-focus-inner,
+#onboarding-overlay-button::-moz-focus-inner {
   border: 0;
 }
 
 /* Keyboard focus specific outline */
 .onboarding-tour-action-button:-moz-focusring {
   outline: 2px solid rgba(0,149,221,0.5);
   outline-offset: 1px;
   -moz-outline-radius: 2px;
--- a/browser/extensions/onboarding/content/onboarding.js
+++ b/browser/extensions/onboarding/content/onboarding.js
@@ -389,23 +389,24 @@ class Onboarding {
   _initUI() {
     if (this.uiInitialized) {
       return;
     }
     this.uiInitialized = true;
     this._tourItems = [];
     this._tourPages = [];
 
+    let { body } = this._window.document;
     this._overlayIcon = this._renderOverlayButton();
     this._overlayIcon.addEventListener("click", this);
-    this._window.document.body.appendChild(this._overlayIcon);
+    body.insertBefore(this._overlayIcon, body.firstChild);
 
     this._overlay = this._renderOverlay();
     this._overlay.addEventListener("click", this);
-    this._window.document.body.appendChild(this._overlay);
+    body.appendChild(this._overlay);
 
     this._loadJS(TOUR_AGENT_JS_URI);
 
     this._initPrefObserver();
     // Doing tour notification takes some effort. Let's do it on idle.
     this._window.requestIdleCallback(() => this._initNotification());
   }
 
@@ -822,18 +823,21 @@ class Onboarding {
 
   _renderOverlayButton() {
     let button = this._window.document.createElement("button");
     let tooltipStringId = this._tourType === "new" ?
       "onboarding.overlay-icon-tooltip" : "onboarding.overlay-icon-tooltip-updated";
     let tooltip = this._bundle.formatStringFromName(tooltipStringId, [BRAND_SHORT_NAME], 1);
     button.setAttribute("aria-label", tooltip);
     button.id = "onboarding-overlay-button";
+    button.setAttribute("aria-haspopup", true);
+    button.setAttribute("aria-controls", "onboarding-overlay-dialog");
     let img = this._window.document.createElement("img");
     img.id = "onboarding-overlay-button-icon";
+    img.setAttribute("role", "presentation");
     img.src = "resource://onboarding/img/overlay-icon.svg";
     button.appendChild(img);
     return button;
   }
 
   _loadTours(tours) {
     let itemsFrag = this._window.document.createDocumentFragment();
     let pagesFrag = this._window.document.createDocumentFragment();
--- a/browser/extensions/onboarding/test/browser/browser.ini
+++ b/browser/extensions/onboarding/test/browser/browser.ini
@@ -1,10 +1,11 @@
 [DEFAULT]
 support-files =
   head.js
 
+[browser_onboarding_accessibility.js]
 [browser_onboarding_notification.js]
 [browser_onboarding_notification_2.js]
 [browser_onboarding_notification_3.js]
 [browser_onboarding_notification_4.js]
 [browser_onboarding_tours.js]
 [browser_onboarding_tourset.js]
new file mode 100644
--- /dev/null
+++ b/browser/extensions/onboarding/test/browser/browser_onboarding_accessibility.js
@@ -0,0 +1,31 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ "use strict";
+
+add_task(async function test_onboarding_overlay_button() {
+  resetOnboardingDefaultState();
+
+  info("Wait for onboarding overlay loaded");
+  let tab = await openTab(ABOUT_HOME_URL);
+  await promiseOnboardingOverlayLoaded(tab.linkedBrowser);
+
+  info("Test accessibility and semantics of the overlay button");
+  await ContentTask.spawn(tab.linkedBrowser, {}, function() {
+    let doc = content.document;
+    let button = doc.body.firstChild;
+    is(button.id, "onboarding-overlay-button",
+      "First child is an overlay button");
+    ok(button.getAttribute("aria-label"),
+      "Onboarding button has an accessible label");
+    is(button.getAttribute("aria-haspopup"), "true",
+      "Onboarding button should indicate that it triggers a popup");
+    is(button.getAttribute("aria-controls"), "onboarding-overlay-dialog",
+      "Onboarding button semantically controls an overlay dialog");
+    is(button.firstChild.getAttribute("role"), "presentation",
+      "Onboarding button icon should have presentation only semantics");
+  });
+
+  await BrowserTestUtils.removeTab(tab);
+});