Bug 1550040 - Add warning icon to contrast warning badge; r=yzen,mtigley
authorFlorens Verschelde <florens@fvsch.com>
Tue, 14 May 2019 19:05:48 +0000
changeset 473822 5df94e4b78cc5fcb8a1cf8f5664b256c346f2f21
parent 473821 1bb020dacad9998406a9bd9a7a6fe1568f718b19
child 473823 1b7aa4ccb45fed7631a62bace49cd6da0ac7d32b
push id36017
push userrgurzau@mozilla.com
push dateWed, 15 May 2019 09:25:56 +0000
treeherdermozilla-central@76bbedc1ec1a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersyzen, mtigley
bugs1550040
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1550040 - Add warning icon to contrast warning badge; r=yzen,mtigley Differential Revision: https://phabricator.services.mozilla.com/D30459
devtools/client/accessibility/accessibility.css
devtools/client/accessibility/components/AccessibilityTreeFilter.js
devtools/client/accessibility/components/Badge.js
devtools/client/accessibility/components/ContrastBadge.js
devtools/client/accessibility/test/jest/components/__snapshots__/accessibility-tree-filter.test.js.snap
devtools/client/accessibility/test/jest/components/__snapshots__/badges.test.js.snap
devtools/client/accessibility/test/jest/components/__snapshots__/contrast-badge.test.js.snap
devtools/client/accessibility/test/jest/components/accessibility-tree-filter.test.js
devtools/client/jar.mn
devtools/client/locales/en-US/accessibility.properties
devtools/client/themes/images/alert-tiny.svg
--- a/devtools/client/accessibility/accessibility.css
+++ b/devtools/client/accessibility/accessibility.css
@@ -358,25 +358,48 @@ body {
   background: var(--theme-toolbar-background);
   font: message-box;
   font-size: var(--accessibility-font-size);
   height: var(--accessibility-toolbar-height);
   color: var(--theme-toolbar-color);
 }
 
 .badge {
+  display: inline-block;
   font: message-box;
+  font-size: var(--theme-body-font-size);
+  line-height: calc(14 / 11);
   border-radius: 3px;
-  padding: 0px 2px;
+  padding: 0px 3px;
   margin-inline-start: 5px;
   color: var(--accessible-label-color);
   background-color: var(--accessible-label-background-color);
   border: 1px solid var(--accessible-label-border-color);
 }
 
+.badge.audit-badge::before {
+  content: "";
+  display: inline-block;
+  vertical-align: -1px;
+  width: 10px;
+  height: 10px;
+  margin-inline-end: 1px;
+  background: url("chrome://devtools/skin/images/alert-tiny.svg") no-repeat;
+  -moz-context-properties: fill;
+  fill: currentColor;
+  opacity: 0.9;
+}
+
+/* improve alignment in high res (where we can use half pixels) */
+@media (min-resolution: 1.5x) {
+  .badge.audit-badge::before {
+    vertical-align: -1.5px;
+  }
+}
+
 .badge.toggle-button {
   color: var(--theme-body-color);
   background-color: var(--badge-interactive-background-color);
   border-color: transparent;
 }
 
 .devtools-toolbar .badge.toggle-button:focus {
   outline: 2px solid var(--accessibility-toolbar-focus);
--- a/devtools/client/accessibility/components/AccessibilityTreeFilter.js
+++ b/devtools/client/accessibility/components/AccessibilityTreeFilter.js
@@ -70,17 +70,17 @@ class AccessibilityTreeFilter extends Co
 
     this.toggleFilter(filterKey);
   }
 
   render() {
     const { auditing, filters } = this.props;
     const filterButtons = Object.entries(filters).map(([filterKey, active]) =>
       ToggleButton({
-        className: "audit-badge badge",
+        className: "badge",
         key: filterKey,
         active,
         label: L10N.getStr(FILTER_LABELS[filterKey]),
         onClick: this.onClick.bind(this, filterKey),
         onKeyDown: this.onKeyDown.bind(this, filterKey),
         busy: auditing === filterKey,
       }));
 
--- a/devtools/client/accessibility/components/Badge.js
+++ b/devtools/client/accessibility/components/Badge.js
@@ -7,25 +7,28 @@
 const { Component } = require("devtools/client/shared/vendor/react");
 const { span } = require("devtools/client/shared/vendor/react-dom-factories");
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
 
 class Badge extends Component {
   static get propTypes() {
     return {
       label: PropTypes.string.isRequired,
+      ariaLabel: PropTypes.string,
       tooltip: PropTypes.string,
     };
   }
 
   render() {
-    const { label, tooltip } = this.props;
+    const { label, ariaLabel, tooltip } = this.props;
 
-    return span({
-      className: "audit-badge badge",
-      title: tooltip,
-      "aria-label": label,
-    },
-      label);
+    return span(
+      {
+        className: "audit-badge badge",
+        title: tooltip,
+        "aria-label": ariaLabel || label,
+      },
+      label
+    );
   }
 }
 
 module.exports = Badge;
--- a/devtools/client/accessibility/components/ContrastBadge.js
+++ b/devtools/client/accessibility/components/ContrastBadge.js
@@ -33,14 +33,15 @@ class ContrastBadge extends Component {
     }
 
     if (score !== SCORES.FAIL) {
       return null;
     }
 
     return Badge({
       label: L10N.getStr("accessibility.badge.contrast"),
+      ariaLabel: L10N.getStr("accessibility.badge.contrast.warning"),
       tooltip: L10N.getStr("accessibility.badge.contrast.tooltip"),
     });
   }
 }
 
 module.exports = ContrastBadge;
--- a/devtools/client/accessibility/test/jest/components/__snapshots__/accessibility-tree-filter.test.js.snap
+++ b/devtools/client/accessibility/test/jest/components/__snapshots__/accessibility-tree-filter.test.js.snap
@@ -1,11 +1,11 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`AccessibilityTreeFilter component: audit filter filtered 1`] = `"<div role=\\"toolbar\\" class=\\"accessibility-tree-filters\\">accessibility.tree.filters<button aria-pressed=\\"true\\" aria-busy=\\"false\\" class=\\"audit-badge badge toggle-button checked\\">accessibility.badge.contrast</button></div>"`;
+exports[`AccessibilityTreeFilter component: audit filter filtered 1`] = `"<div role=\\"toolbar\\" class=\\"accessibility-tree-filters\\">accessibility.tree.filters<button aria-pressed=\\"true\\" aria-busy=\\"false\\" class=\\"badge toggle-button checked\\">accessibility.badge.contrast</button></div>"`;
 
-exports[`AccessibilityTreeFilter component: audit filter filtered auditing 1`] = `"<div role=\\"toolbar\\" class=\\"accessibility-tree-filters\\">accessibility.tree.filters<button aria-pressed=\\"true\\" aria-busy=\\"true\\" class=\\"audit-badge badge toggle-button checked devtools-throbber\\">accessibility.badge.contrast</button></div>"`;
+exports[`AccessibilityTreeFilter component: audit filter filtered auditing 1`] = `"<div role=\\"toolbar\\" class=\\"accessibility-tree-filters\\">accessibility.tree.filters<button aria-pressed=\\"true\\" aria-busy=\\"true\\" class=\\"badge toggle-button checked devtools-throbber\\">accessibility.badge.contrast</button></div>"`;
 
-exports[`AccessibilityTreeFilter component: audit filter not filtered 1`] = `"<div role=\\"toolbar\\" class=\\"accessibility-tree-filters\\">accessibility.tree.filters<button aria-pressed=\\"false\\" aria-busy=\\"false\\" class=\\"audit-badge badge toggle-button\\">accessibility.badge.contrast</button></div>"`;
+exports[`AccessibilityTreeFilter component: audit filter not filtered 1`] = `"<div role=\\"toolbar\\" class=\\"accessibility-tree-filters\\">accessibility.tree.filters<button aria-pressed=\\"false\\" aria-busy=\\"false\\" class=\\"badge toggle-button\\">accessibility.badge.contrast</button></div>"`;
 
-exports[`AccessibilityTreeFilter component: audit filter not filtered auditing 1`] = `"<div role=\\"toolbar\\" class=\\"accessibility-tree-filters\\">accessibility.tree.filters<button aria-pressed=\\"false\\" aria-busy=\\"true\\" class=\\"audit-badge badge toggle-button devtools-throbber\\">accessibility.badge.contrast</button></div>"`;
+exports[`AccessibilityTreeFilter component: audit filter not filtered auditing 1`] = `"<div role=\\"toolbar\\" class=\\"accessibility-tree-filters\\">accessibility.tree.filters<button aria-pressed=\\"false\\" aria-busy=\\"true\\" class=\\"badge toggle-button devtools-throbber\\">accessibility.badge.contrast</button></div>"`;
 
-exports[`AccessibilityTreeFilter component: toggle filter 1`] = `"<div role=\\"toolbar\\" class=\\"accessibility-tree-filters\\">accessibility.tree.filters<button aria-pressed=\\"false\\" aria-busy=\\"false\\" class=\\"audit-badge badge toggle-button\\">accessibility.badge.contrast</button></div>"`;
+exports[`AccessibilityTreeFilter component: toggle filter 1`] = `"<div role=\\"toolbar\\" class=\\"accessibility-tree-filters\\">accessibility.tree.filters<button aria-pressed=\\"false\\" aria-busy=\\"false\\" class=\\"badge toggle-button\\">accessibility.badge.contrast</button></div>"`;
--- a/devtools/client/accessibility/test/jest/components/__snapshots__/badges.test.js.snap
+++ b/devtools/client/accessibility/test/jest/components/__snapshots__/badges.test.js.snap
@@ -1,13 +1,13 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`Badges component: contrast ratio fail range render 1`] = `"<span class=\\"badges\\" role=\\"group\\" aria-label=\\"accessibility.badges\\"><span class=\\"audit-badge badge\\" title=\\"accessibility.badge.contrast.tooltip\\" aria-label=\\"accessibility.badge.contrast\\">accessibility.badge.contrast</span></span>"`;
+exports[`Badges component: contrast ratio fail range render 1`] = `"<span class=\\"badges\\" role=\\"group\\" aria-label=\\"accessibility.badges\\"><span class=\\"audit-badge badge\\" title=\\"accessibility.badge.contrast.tooltip\\" aria-label=\\"accessibility.badge.contrast.warning\\">accessibility.badge.contrast</span></span>"`;
 
-exports[`Badges component: contrast ratio fail render 1`] = `"<span class=\\"badges\\" role=\\"group\\" aria-label=\\"accessibility.badges\\"><span class=\\"audit-badge badge\\" title=\\"accessibility.badge.contrast.tooltip\\" aria-label=\\"accessibility.badge.contrast\\">accessibility.badge.contrast</span></span>"`;
+exports[`Badges component: contrast ratio fail render 1`] = `"<span class=\\"badges\\" role=\\"group\\" aria-label=\\"accessibility.badges\\"><span class=\\"audit-badge badge\\" title=\\"accessibility.badge.contrast.tooltip\\" aria-label=\\"accessibility.badge.contrast.warning\\">accessibility.badge.contrast</span></span>"`;
 
 exports[`Badges component: contrast ratio success render 1`] = `"<span class=\\"badges\\" role=\\"group\\" aria-label=\\"accessibility.badges\\"></span>"`;
 
 exports[`Badges component: empty checks render 1`] = `null`;
 
 exports[`Badges component: no props render 1`] = `null`;
 
 exports[`Badges component: null checks render 1`] = `null`;
--- a/devtools/client/accessibility/test/jest/components/__snapshots__/contrast-badge.test.js.snap
+++ b/devtools/client/accessibility/test/jest/components/__snapshots__/contrast-badge.test.js.snap
@@ -1,11 +1,11 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`ContrastBadge component: error render 1`] = `null`;
 
-exports[`ContrastBadge component: fail render 1`] = `"<span class=\\"audit-badge badge\\" title=\\"accessibility.badge.contrast.tooltip\\" aria-label=\\"accessibility.badge.contrast\\">accessibility.badge.contrast</span>"`;
+exports[`ContrastBadge component: fail render 1`] = `"<span class=\\"audit-badge badge\\" title=\\"accessibility.badge.contrast.tooltip\\" aria-label=\\"accessibility.badge.contrast.warning\\">accessibility.badge.contrast</span>"`;
 
 exports[`ContrastBadge component: success large text render 1`] = `null`;
 
 exports[`ContrastBadge component: success range render 1`] = `null`;
 
 exports[`ContrastBadge component: success render 1`] = `null`;
--- a/devtools/client/accessibility/test/jest/components/accessibility-tree-filter.test.js
+++ b/devtools/client/accessibility/test/jest/components/accessibility-tree-filter.test.js
@@ -33,19 +33,19 @@ describe("AccessibilityTreeFilter compon
     expect(toolbar.is("div")).toBe(true);
     expect(toolbar.prop("role")).toBe("toolbar");
 
     const filterButtons = filters.find(ToggleButton);
     expect(filterButtons.length).toBe(1);
 
     const button = filterButtons.at(0).childAt(0);
     expect(button.is("button")).toBe(true);
-    expect(button.hasClass("audit-badge")).toBe(true);
     expect(button.hasClass("badge")).toBe(true);
     expect(button.hasClass("toggle-button")).toBe(true);
+    expect(button.hasClass("audit-badge")).toBe(false);
     expect(button.prop("aria-pressed")).toBe(false);
     expect(button.text()).toBe("accessibility.badge.contrast");
   });
 
   it("audit filter filtered", () => {
     const store = setupStore({
       preloadedState: { audit: { filters: { [FILTERS.CONTRAST]: true }}},
     });
@@ -100,18 +100,18 @@ describe("AccessibilityTreeFilter compon
 
   it("toggle filter", () => {
     const store = setupStore();
     const wrapper = mount(Provider({store}, AccessibilityTreeFilter()));
     expect(wrapper.html()).toMatchSnapshot();
 
     const filterInstance = wrapper.find(AccessibilityTreeFilterClass).instance();
     filterInstance.toggleFilter = jest.fn();
-    wrapper.find("button.audit-badge.badge").simulate("keydown", { key: " " });
+    wrapper.find("button.toggle-button.badge").simulate("keydown", { key: " " });
     expect(filterInstance.toggleFilter.mock.calls.length).toBe(1);
 
-    wrapper.find("button.audit-badge.badge").simulate("keydown", { key: "Enter" });
+    wrapper.find("button.toggle-button.badge").simulate("keydown", { key: "Enter" });
     expect(filterInstance.toggleFilter.mock.calls.length).toBe(2);
 
-    wrapper.find("button.audit-badge.badge").simulate("click", { clientX: 1 });
+    wrapper.find("button.toggle-button.badge").simulate("click", { clientX: 1 });
     expect(filterInstance.toggleFilter.mock.calls.length).toBe(3);
   });
 });
--- a/devtools/client/jar.mn
+++ b/devtools/client/jar.mn
@@ -60,16 +60,17 @@ devtools.jar:
     skin/dark-theme.css (themes/dark-theme.css)
     skin/light-theme.css (themes/light-theme.css)
     skin/toolbars.css (themes/toolbars.css)
     skin/toolbox.css (themes/toolbox.css)
     skin/tooltips.css (themes/tooltips.css)
     skin/images/accessibility.svg (themes/images/accessibility.svg)
     skin/images/add.svg (themes/images/add.svg)
     skin/images/alert.svg (themes/images/alert.svg)
+    skin/images/alert-tiny.svg (themes/images/alert-tiny.svg)
     skin/images/arrow.svg (themes/images/arrow.svg)
     skin/images/arrow-big.svg (themes/images/arrow-big.svg)
     skin/images/arrowhead-left.svg (themes/images/arrowhead-left.svg)
     skin/images/arrowhead-right.svg (themes/images/arrowhead-right.svg)
     skin/images/arrowhead-down.svg (themes/images/arrowhead-down.svg)
     skin/images/arrowhead-up.svg (themes/images/arrowhead-up.svg)
     skin/images/breadcrumbs-divider.svg (themes/images/breadcrumbs-divider.svg)
     skin/images/checkbox.svg (themes/images/checkbox.svg)
--- a/devtools/client/locales/en-US/accessibility.properties
+++ b/devtools/client/locales/en-US/accessibility.properties
@@ -158,16 +158,22 @@ accessibility.contrast.annotation.fail=D
 accessibility.badges=Accessibility checks
 
 # LOCALIZATION NOTE (accessibility.badge.contrast): A title text for the badge
 # that is rendered within the accessible row in the accessibility tree for a
 # given accessible object that does not satisfy the WCAG guideline for colour
 # contrast.
 accessibility.badge.contrast=contrast
 
+# LOCALIZATION NOTE (accessibility.badge.contrast.warning): A label for the
+# badge and attached warning icon that is rendered within the accessible row in
+# the accessibility tree for a given accessible object that does not satisfy the
+# WCAG guideline for colour contrast.
+accessibility.badge.contrast.warning=contrast warning
+
 # LOCALIZATION NOTE (accessibility.badge.contrast.tooltip): A title text for the
 # badge tooltip that is rendered on mouse hover over the badge in the accessible
 # row in the accessibility tree for a given accessible object that does not
 # satisfy the WCAG guideline for colour contrast.
 accessibility.badge.contrast.tooltip=Does not meet WCAG standards for accessible text.
 
 # LOCALIZATION NOTE (accessibility.tree.filters): A title text for the toolbar
 # within the main accessibility panel that contains a list of filters to be for
new file mode 100644
--- /dev/null
+++ b/devtools/client/themes/images/alert-tiny.svg
@@ -0,0 +1,6 @@
+<!-- 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/. -->
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10" width="10" height="10">
+  <path fill="context-fill" fill-rule="evenodd" d="M4.94.76a.5.5 0 0 0-.88 0l-4 7.5A.5.5 0 0 0 .5 9h8a.5.5 0 0 0 .44-.74l-4-7.5zM4.5 2.8a.7.7 0 0 0-.7.7v1.8a.7.7 0 1 0 1.4 0V3.5a.7.7 0 0 0-.7-.7zm0 5.4a.7.7 0 1 0 0-1.4.7.7 0 0 0 0 1.4z"/>
+</svg>