Bug 1482454 - add learn more links across accessibility panel. r=gl, flod

MozReview-Commit-ID: GWrdjnzlS8b
This commit is contained in:
Yura Zenevich 2018-08-20 14:44:12 -04:00
Родитель a6ff06e3c5
Коммит d3673a24f2
9 изменённых файлов: 273 добавлений и 6 удалений

Просмотреть файл

@ -14,11 +14,15 @@
--accessibility-tree-row-height: 21px;
--accessibility-unfocused-tree-focused-node-background: var(--grey-20);
--accessibility-tree-focused-node-twisty-brightness: brightness(20%);
--accessibility-link-color: var(--blue-60);
--accessibility-link-color-active: var(--blue-70);
}
:root.theme-dark {
--accessibility-unfocused-tree-focused-node-background: var(--grey-70);
--accessibility-tree-focused-node-twisty-brightness: unset;
--accessibility-link-color: var(--theme-highlight-blue);
--accessibility-link-color-active: var(--blue-40);
}
/* General */
@ -92,6 +96,41 @@ body {
-moz-outline-radius: 2px;
}
.devtools-toolbar {
display: flex;
align-items: center;
}
.devtools-toolbar .help {
cursor: pointer;
width: 18px;
margin-inline-start: auto;
margin-inline-end: 3px;
background: transparent;
}
.devtools-toolbar .help .btn-content {
display: block;
padding: 0;
background-color: var(--theme-body-color);
width: 16px;
height: 16px;
mask: url("chrome://devtools/skin/images/help.svg") no-repeat;
}
.devtools-toolbar .help:focus {
outline: 2px solid var(--accessibility-toolbar-focus);
box-shadow: 0 0 0 3px var(--accessibility-toolbar-focus-alpha30);
border-radius: 2px;
outline-offset: -1px;
-moz-outline-radius: 2px;
}
.devtools-toolbar .help:focus > .btn-content {
outline: none;
box-shadow: none;
}
/* Description */
.description {
color: var(--theme-toolbar-color);
@ -102,10 +141,18 @@ body {
width: 50vw;
}
/* To ensure that the message does not look squished in vertical mode, increase its width
when the toolbox is narrow */
@media (max-width: 700px) {
.description {
width: 80vw;
}
}
.description .general {
display: flex;
align-items: center;
margin-bottom: 1.7em;
margin-bottom: 1em;
}
.description img {
@ -122,6 +169,26 @@ body {
margin: auto;
}
.description .link {
color: var(--accessibility-link-color);
cursor: pointer;
outline: 0;
}
.description .link:hover:not(:focus) {
text-decoration: underline;
}
.description .link:focus:not(:active) {
box-shadow: 0 0 0 2px var(--accessibility-toolbar-focus), 0 0 0 4px var(--accessibility-toolbar-focus-alpha30);
border-radius: 2px;
}
.description .link:active {
color: var(--accessibility-link-color-active);
text-decoration: underline;
}
/* TreeView Customization */
.split-box:not(.horz) .main-panel {
height: calc(100vh - var(--accessibility-toolbar-height));

Просмотреть файл

@ -12,12 +12,13 @@ const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const Button = createFactory(require("./Button"));
const LearnMoreLink = createFactory(require("./LearnMoreLink"));
const { enable, updateCanBeEnabled } = require("../actions/ui");
// Localization
const { L10N } = require("../utils/l10n");
const { A11Y_SERVICE_ENABLED_COUNT } = require("../constants");
const { A11Y_LEARN_MORE_LINK, A11Y_SERVICE_ENABLED_COUNT } = require("../constants");
class OldVersionDescription extends Component {
render() {
@ -99,13 +100,23 @@ class Description extends Component {
}
return (
div({ className: "description" },
p({ className: "general" },
div({ className: "description", role: "presentation" },
div({ className: "general", role: "presentation" },
img({
src: "chrome://devtools/skin/images/accessibility.svg",
alt: L10N.getStr("accessibility.logo")
}),
L10N.getStr("accessibility.description.general")),
div({ role: "presentation" },
LearnMoreLink({
href: A11Y_LEARN_MORE_LINK +
"?utm_source=devtools&utm_medium=a11y-panel-description",
learnMoreStringKey: "accessibility.learnMore",
l10n: L10N,
messageStringKey: "accessibility.description.general.p1"
}),
p({}, L10N.getStr("accessibility.description.general.p2"))
)
),
Button({
id: "accessibility-enable-button",
onClick: this.onEnable,

Просмотреть файл

@ -0,0 +1,60 @@
/* 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";
const { Component } = require("devtools/client/shared/vendor/react");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { p, a } = require("devtools/client/shared/vendor/react-dom-factories");
const { openDocLink } = require("devtools/client/shared/link");
/**
* Localization friendly component for rendering a block of text with a "Learn more" link
* as a part of it.
*/
class LearnMoreLink extends Component {
static get propTypes() {
return {
href: PropTypes.string,
learnMoreStringKey: PropTypes.string.isRequired,
l10n: PropTypes.object.isRequired,
messageStringKey: PropTypes.string.isRequired,
onClick: PropTypes.func
};
}
static get defaultProps() {
return {
href: "#",
learnMoreStringKey: null,
l10n: null,
messageStringKey: null,
onClick: LearnMoreLink.openDocOnClick
};
}
static openDocOnClick(event) {
event.preventDefault();
openDocLink(event.target.href);
}
render() {
const { href, learnMoreStringKey, l10n, messageStringKey, onClick } = this.props;
const learnMoreString = l10n.getStr(learnMoreStringKey);
const messageString = l10n.getFormatStr(messageStringKey, learnMoreString);
// Split the paragraph string with the link as a separator, and include the link into
// results.
const re = new RegExp(`(\\b${learnMoreString}\\b)`);
const contents = messageString.split(re);
contents[1] = a({ className: "link", href, onClick }, contents[1]);
return (
p({}, ...contents)
);
}
}
module.exports = LearnMoreLink;

Просмотреть файл

@ -13,6 +13,9 @@ const Button = createFactory(require("./Button"));
const { connect } = require("devtools/client/shared/vendor/react-redux");
const { disable, updateCanBeDisabled } = require("../actions/ui");
const { A11Y_LEARN_MORE_LINK } = require("../constants");
const { openDocLink } = require("devtools/client/shared/link");
class Toolbar extends Component {
static get propTypes() {
return {
@ -56,6 +59,11 @@ class Toolbar extends Component {
.catch(() => this.setState({ disabling: false }));
}
onLearnMoreClick() {
openDocLink(A11Y_LEARN_MORE_LINK +
"?utm_source=devtools&utm_medium=a11y-panel-toolbar");
}
render() {
const { canBeDisabled } = this.props;
const { disabling } = this.state;
@ -82,7 +90,12 @@ class Toolbar extends Component {
disabled: disabling || isDisabled,
busy: disabling,
title
}, L10N.getStr(disableButtonStr)))
}, L10N.getStr(disableButtonStr)),
Button({
className: "help",
title: L10N.getStr("accessibility.learnMore"),
onClick: this.onLearnMoreClick
}))
);
}
}

Просмотреть файл

@ -8,6 +8,7 @@ DevToolsModules(
'Accessible.js',
'Button.js',
'Description.js',
'LearnMoreLink.js',
'MainFrame.js',
'RightSidebar.js',
'Toolbar.js'

Просмотреть файл

@ -63,3 +63,7 @@ exports.ACCESSIBLE_EVENTS = [
// Telemetry name constants.
exports.A11Y_SERVICE_DURATION = "DEVTOOLS_ACCESSIBILITY_SERVICE_TIME_ACTIVE_SECONDS";
exports.A11Y_SERVICE_ENABLED_COUNT = "devtools.accessibility.service_enabled_count";
// URL constants
exports.A11Y_LEARN_MORE_LINK =
"https://developer.mozilla.org/docs/Tools/Accessibility_inspector";

Просмотреть файл

@ -2,4 +2,5 @@
support-files =
head.js
[test_accessible_learnMoreLink.html]
[test_accessible_openLink.html]

Просмотреть файл

@ -0,0 +1,95 @@
<!-- 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/. -->
<!DOCTYPE HTML>
<html>
<!--
Test that LearnMoreLink parses and renders correctly text with learn more links.
-->
<head>
<meta charset="utf-8">
<title>LearnMoreLink component test</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
<link rel="stylesheet" href="chrome://devtools/skin/light-theme.css" type="text/css">
</head>
<body>
<pre id="test">
<script src="head.js" type="application/javascript"></script>
<script type="application/javascript">
"use strict";
window.onload = async function() {
try {
const { gDevTools } = require("devtools/client/framework/devtools");
const Services = browserRequire("Services");
const ReactDOM = browserRequire("devtools/client/shared/vendor/react-dom");
const { createFactory } = browserRequire("devtools/client/shared/vendor/react");
const { Simulate } =
browserRequire("devtools/client/shared/vendor/react-dom-test-utils");
const LearnMoreLink = createFactory(
browserRequire("devtools/client/accessibility/components/LearnMoreLink"));
class MockL10N {
constructor(bundle) {
this.bundle = bundle;
}
getStr(name) {
return this.bundle[name];
}
getFormatStr(name, ...args) {
let index = 0;
return this.bundle[name].replace("%S", () => args[index++]);
}
}
function testLinkClicked(link, expectedUrl) {
const browserWindow = Services.wm.getMostRecentWindow(gDevTools.chromeWindowType);
const defaultOpenWebLinkIn = browserWindow.openWebLinkIn;
const checker = Symbol();
let onClickUrl = checker;
browserWindow.openWebLinkIn = url => {
onClickUrl = url;
};
Simulate.click(link);
ok(onClickUrl !== checker, "Link was clicked");
is(onClickUrl, expectedUrl, "Correct URL is opened");
browserWindow.openWebLinkIn = defaultOpenWebLinkIn;
}
const href = "http://example.com/";
const l10n = new MockL10N({
message: "This is a message that contains a link. %S",
link: "Learn more"
});
const learnMoreLink = LearnMoreLink(
{ href, l10n, learnMoreStringKey: "link", messageStringKey: "message" });
ok(LearnMoreLink, "Should be able to create LearnMoreLink instances");
ReactDOM.render(learnMoreLink, document.body);
const p = document.querySelector("p");
is(p.textContent, "This is a message that contains a link. Learn more",
"Text content for the whole paragraph is correct");
const link = p.querySelector(".link");
ok(link, "Link was rendered");
is(link.textContent, "Learn more", "Text content for link is correct");
testLinkClicked(link, href);
} catch (e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
};
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -77,11 +77,26 @@ accessibility.enable.disabledTitle=Accessibility service can not be turned on. I
# enabled.
accessibility.enable.enabledTitle=Accessibility service will be turned on for all tabs and windows.
# LOCALIZATION NOTE (accessibility.learnMore): A text that is used as is or as textual
# description in places that link to accessibility inspector documentation.
accessibility.learnMore=Learn more
# LOCALIZATION NOTE (accessibility.description.general): A title text used when
# accessibility service description is provided before accessibility inspector
# is enabled.
accessibility.description.general=Accessibility features are deactivated by default because they negatively impact performance. Consider turning off accessibility features before using other Developer Tools panels.
# LOCALIZATION NOTE (accessibility.description.general.p1): A title text for the first
# paragraph, used when accessibility service description is provided before accessibility
# inspector is enabled. %S in the content will be replaced by a link at run time
# with the accessibility.learnMore string.
accessibility.description.general.p1=Accessibility Inspector lets you examine the current pages accessibility tree, which is used by screen readers and other assistive technologies. %S
# LOCALIZATION NOTE (accessibility.description.general.p2): A title text for the second
# paragraph, used when accessibility service description is provided before accessibility
# inspector is enabled.
accessibility.description.general.p2=Accessibility features may affect the performance of other developer tools panels and should be turned off when not in use.
# LOCALIZATION NOTE (accessibility.description.oldVersion): A title text used
# when accessibility service description is provided when a client is connected
# to an older version of accessibility actor.