tor-browser

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

ColorContrastAccessibility.js (5475B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 const {
      8  Component,
      9  createFactory,
     10 } = require("resource://devtools/client/shared/vendor/react.mjs");
     11 const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.mjs");
     12 const {
     13  div,
     14  span,
     15  h3,
     16 } = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
     17 const LearnMoreLink = createFactory(
     18  require("resource://devtools/client/accessibility/components/LearnMoreLink.js")
     19 );
     20 
     21 const {
     22  A11Y_CONTRAST_LEARN_MORE_LINK,
     23 } = require("resource://devtools/client/accessibility/constants.js");
     24 const {
     25  L10N,
     26 } = require("resource://devtools/client/accessibility/utils/l10n.js");
     27 
     28 /**
     29 * Component that renders a colour contrast value along with a swatch preview of what the
     30 * text and background colours are.
     31 */
     32 class ContrastValueClass extends Component {
     33  static get propTypes() {
     34    return {
     35      backgroundColor: PropTypes.array.isRequired,
     36      color: PropTypes.array.isRequired,
     37      value: PropTypes.number.isRequired,
     38      score: PropTypes.string,
     39    };
     40  }
     41 
     42  render() {
     43    const { backgroundColor, color, value, score } = this.props;
     44 
     45    const className = ["accessibility-contrast-value", score].join(" ");
     46 
     47    return span(
     48      {
     49        className,
     50        role: "presentation",
     51        style: {
     52          "--accessibility-contrast-color": `rgba(${color})`,
     53          "--accessibility-contrast-bg": `rgba(${backgroundColor})`,
     54        },
     55      },
     56      value.toFixed(2)
     57    );
     58  }
     59 }
     60 
     61 const ContrastValue = createFactory(ContrastValueClass);
     62 
     63 /**
     64 * Component that renders labeled colour contrast values together with the large text
     65 * indiscator.
     66 */
     67 class ColorContrastAccessibilityClass extends Component {
     68  static get propTypes() {
     69    return {
     70      error: PropTypes.string,
     71      isLargeText: PropTypes.bool.isRequired,
     72      color: PropTypes.array.isRequired,
     73      value: PropTypes.number,
     74      min: PropTypes.number,
     75      max: PropTypes.number,
     76      backgroundColor: PropTypes.array,
     77      backgroundColorMin: PropTypes.array,
     78      backgroundColorMax: PropTypes.array,
     79      score: PropTypes.string,
     80      scoreMin: PropTypes.string,
     81      scoreMax: PropTypes.string,
     82    };
     83  }
     84 
     85  render() {
     86    const {
     87      error,
     88      isLargeText,
     89      color,
     90      value,
     91      backgroundColor,
     92      score,
     93      min,
     94      backgroundColorMin,
     95      scoreMin,
     96      max,
     97      backgroundColorMax,
     98      scoreMax,
     99    } = this.props;
    100 
    101    const children = [];
    102 
    103    if (error) {
    104      children.push(
    105        span(
    106          {
    107            className: "accessibility-color-contrast-error",
    108            role: "presentation",
    109          },
    110          L10N.getStr("accessibility.contrast.error")
    111        )
    112      );
    113 
    114      return div(
    115        {
    116          role: "presentation",
    117          tabIndex: "-1",
    118          className: "accessibility-color-contrast",
    119        },
    120        ...children
    121      );
    122    }
    123 
    124    if (value) {
    125      children.push(ContrastValue({ score, color, backgroundColor, value }));
    126    } else {
    127      children.push(
    128        ContrastValue({
    129          score: scoreMin,
    130          color,
    131          backgroundColor: backgroundColorMin,
    132          value: min,
    133        }),
    134        div({
    135          role: "presentation",
    136          tabIndex: "-1",
    137          className: "accessibility-color-contrast-separator",
    138        }),
    139        ContrastValue({
    140          score: scoreMax,
    141          color,
    142          backgroundColor: backgroundColorMax,
    143          value: max,
    144        })
    145      );
    146    }
    147 
    148    if (isLargeText) {
    149      children.push(
    150        span(
    151          {
    152            className: "accessibility-color-contrast-large-text",
    153            role: "presentation",
    154            title: L10N.getStr("accessibility.contrast.large.title"),
    155          },
    156          L10N.getStr("accessibility.contrast.large.text")
    157        )
    158      );
    159    }
    160 
    161    return div(
    162      {
    163        role: "presentation",
    164        tabIndex: "-1",
    165        className: "accessibility-color-contrast",
    166      },
    167      ...children
    168    );
    169  }
    170 }
    171 
    172 const ColorContrastAccessibility = createFactory(
    173  ColorContrastAccessibilityClass
    174 );
    175 
    176 class ContrastAnnotationClass extends Component {
    177  static get propTypes() {
    178    return {
    179      score: PropTypes.string,
    180    };
    181  }
    182 
    183  render() {
    184    const { score } = this.props;
    185 
    186    return LearnMoreLink({
    187      className: "accessibility-check-annotation",
    188      href: A11Y_CONTRAST_LEARN_MORE_LINK,
    189      learnMoreStringKey: "accessibility.learnMore",
    190      l10n: L10N,
    191      messageStringKey: `accessibility.contrast.annotation.${score}`,
    192    });
    193  }
    194 }
    195 
    196 const ContrastAnnotation = createFactory(ContrastAnnotationClass);
    197 
    198 class ColorContrastCheck extends Component {
    199  static get propTypes() {
    200    return {
    201      error: PropTypes.string.isRequired,
    202    };
    203  }
    204 
    205  render() {
    206    const { error } = this.props;
    207 
    208    return div(
    209      {
    210        role: "presentation",
    211        tabIndex: "-1",
    212        className: "accessibility-check",
    213      },
    214      h3(
    215        {
    216          className: "accessibility-check-header",
    217        },
    218        L10N.getStr("accessibility.contrast.header")
    219      ),
    220      ColorContrastAccessibility(this.props),
    221      !error && ContrastAnnotation(this.props)
    222    );
    223  }
    224 }
    225 
    226 module.exports = {
    227  ColorContrastAccessibility: ColorContrastAccessibilityClass,
    228  ColorContrastCheck,
    229 };