diff options
Diffstat (limited to 'devtools/client/accessibility/components/ColorContrastAccessibility.js')
-rw-r--r-- | devtools/client/accessibility/components/ColorContrastAccessibility.js | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/devtools/client/accessibility/components/ColorContrastAccessibility.js b/devtools/client/accessibility/components/ColorContrastAccessibility.js new file mode 100644 index 0000000000..117ab67593 --- /dev/null +++ b/devtools/client/accessibility/components/ColorContrastAccessibility.js @@ -0,0 +1,229 @@ +/* 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, + createFactory, +} = require("resource://devtools/client/shared/vendor/react.js"); +const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.js"); +const { + div, + span, + h3, +} = require("resource://devtools/client/shared/vendor/react-dom-factories.js"); +const LearnMoreLink = createFactory( + require("resource://devtools/client/accessibility/components/LearnMoreLink.js") +); + +const { + A11Y_CONTRAST_LEARN_MORE_LINK, +} = require("resource://devtools/client/accessibility/constants.js"); +const { + L10N, +} = require("resource://devtools/client/accessibility/utils/l10n.js"); + +/** + * Component that renders a colour contrast value along with a swatch preview of what the + * text and background colours are. + */ +class ContrastValueClass extends Component { + static get propTypes() { + return { + backgroundColor: PropTypes.array.isRequired, + color: PropTypes.array.isRequired, + value: PropTypes.number.isRequired, + score: PropTypes.string, + }; + } + + render() { + const { backgroundColor, color, value, score } = this.props; + + const className = ["accessibility-contrast-value", score].join(" "); + + return span( + { + className, + role: "presentation", + style: { + "--accessibility-contrast-color": `rgba(${color})`, + "--accessibility-contrast-bg": `rgba(${backgroundColor})`, + }, + }, + value.toFixed(2) + ); + } +} + +const ContrastValue = createFactory(ContrastValueClass); + +/** + * Component that renders labeled colour contrast values together with the large text + * indiscator. + */ +class ColorContrastAccessibilityClass extends Component { + static get propTypes() { + return { + error: PropTypes.string, + isLargeText: PropTypes.bool.isRequired, + color: PropTypes.array.isRequired, + value: PropTypes.number, + min: PropTypes.number, + max: PropTypes.number, + backgroundColor: PropTypes.array, + backgroundColorMin: PropTypes.array, + backgroundColorMax: PropTypes.array, + score: PropTypes.string, + scoreMin: PropTypes.string, + scoreMax: PropTypes.string, + }; + } + + render() { + const { + error, + isLargeText, + color, + value, + backgroundColor, + score, + min, + backgroundColorMin, + scoreMin, + max, + backgroundColorMax, + scoreMax, + } = this.props; + + const children = []; + + if (error) { + children.push( + span( + { + className: "accessibility-color-contrast-error", + role: "presentation", + }, + L10N.getStr("accessibility.contrast.error") + ) + ); + + return div( + { + role: "presentation", + tabIndex: "-1", + className: "accessibility-color-contrast", + }, + ...children + ); + } + + if (value) { + children.push(ContrastValue({ score, color, backgroundColor, value })); + } else { + children.push( + ContrastValue({ + score: scoreMin, + color, + backgroundColor: backgroundColorMin, + value: min, + }), + div({ + role: "presentation", + tabIndex: "-1", + className: "accessibility-color-contrast-separator", + }), + ContrastValue({ + score: scoreMax, + color, + backgroundColor: backgroundColorMax, + value: max, + }) + ); + } + + if (isLargeText) { + children.push( + span( + { + className: "accessibility-color-contrast-large-text", + role: "presentation", + title: L10N.getStr("accessibility.contrast.large.title"), + }, + L10N.getStr("accessibility.contrast.large.text") + ) + ); + } + + return div( + { + role: "presentation", + tabIndex: "-1", + className: "accessibility-color-contrast", + }, + ...children + ); + } +} + +const ColorContrastAccessibility = createFactory( + ColorContrastAccessibilityClass +); + +class ContrastAnnotationClass extends Component { + static get propTypes() { + return { + score: PropTypes.string, + }; + } + + render() { + const { score } = this.props; + + return LearnMoreLink({ + className: "accessibility-check-annotation", + href: A11Y_CONTRAST_LEARN_MORE_LINK, + learnMoreStringKey: "accessibility.learnMore", + l10n: L10N, + messageStringKey: `accessibility.contrast.annotation.${score}`, + }); + } +} + +const ContrastAnnotation = createFactory(ContrastAnnotationClass); + +class ColorContrastCheck extends Component { + static get propTypes() { + return { + error: PropTypes.string.isRequired, + }; + } + + render() { + const { error } = this.props; + + return div( + { + role: "presentation", + tabIndex: "-1", + className: "accessibility-check", + }, + h3( + { + className: "accessibility-check-header", + }, + L10N.getStr("accessibility.contrast.header") + ), + ColorContrastAccessibility(this.props), + !error && ContrastAnnotation(this.props) + ); + } +} + +module.exports = { + ColorContrastAccessibility: ColorContrastAccessibilityClass, + ColorContrastCheck, +}; |