tor-browser

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

fxview-empty-state.mjs (5194B)


      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 import {
      6  html,
      7  classMap,
      8  repeat,
      9 } from "chrome://global/content/vendor/lit.all.mjs";
     10 import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
     11 import { navigateToLink } from "chrome://browser/content/firefoxview/helpers.mjs";
     12 
     13 /**
     14 * An empty state card to be used throughout Firefox View
     15 *
     16 * @property {string} headerLabel - (Optional) The l10n id for the header text for the empty/error state
     17 * @property {object} headerArgs - (Optional) The l10n args for the header text for the empty/error state
     18 * @property {string} isInnerCard - (Optional) True if the card is displayed within another card and needs a border instead of box shadow
     19 * @property {boolean} isSelectedTab - (Optional) True if the component is the selected navigation tab - defaults to false
     20 * @property {Array} descriptionLabels - (Optional) An array of l10n ids for the secondary description text for the empty/error state
     21 * @property {object} descriptionLink - (Optional) An object describing the l10n name and url needed within a description label
     22 * @property {string} mainImageUrl - (Optional) The chrome:// url for the main image of the empty/error state
     23 * @property {string} errorGrayscale - (Optional) The image should be shown in gray scale
     24 * @property {boolean} openLinkInParentWindow - (Optional) The link, when clicked, should be opened programatically in the parent window.
     25 */
     26 class FxviewEmptyState extends MozLitElement {
     27  constructor() {
     28    super();
     29    this.isSelectedTab = false;
     30    this.descriptionLabels = [];
     31    this.headerArgs = {};
     32  }
     33 
     34  static properties = {
     35    headerLabel: { type: String },
     36    headerArgs: { type: Object },
     37    isInnerCard: { type: Boolean },
     38    isSelectedTab: { type: Boolean },
     39    descriptionLabels: { type: Array },
     40    desciptionLink: { type: Object },
     41    mainImageUrl: { type: String },
     42    errorGrayscale: { type: Boolean },
     43    openLinkInParentWindow: { type: Boolean },
     44  };
     45 
     46  static queries = {
     47    headerEl: ".header",
     48    descriptionEls: { all: ".description" },
     49  };
     50 
     51  linkTemplate(descriptionLink) {
     52    if (!descriptionLink) {
     53      return html``;
     54    }
     55    return html`<a
     56      data-l10n-name=${descriptionLink.name}
     57      href=${descriptionLink.url}
     58      target=${descriptionLink?.sameTarget ? "_self" : "_blank"}
     59    ></a>`;
     60  }
     61 
     62  render() {
     63    return html`
     64      <link
     65        rel="stylesheet"
     66        href="chrome://browser/content/firefoxview/fxview-empty-state.css"
     67      />
     68      <card-container
     69        hideHeader="true"
     70        exportparts="image"
     71        ?isInnerCard=${this.isInnerCard}
     72        id="card-container"
     73        isEmptyState="true"
     74        role="group"
     75        aria-labelledby="header"
     76        aria-describedby="description"
     77      >
     78        <div
     79          slot="main"
     80          part="container"
     81          class=${classMap({
     82            selectedTab: this.isSelectedTab,
     83            imageHidden: !this.mainImageUrl,
     84          })}
     85        >
     86          <div class="image-container" part="image-container">
     87            <img
     88              class=${classMap({
     89                image: true,
     90                greyscale: this.errorGrayscale,
     91              })}
     92              part="image"
     93              role="presentation"
     94              alt=""
     95              ?hidden=${!this.mainImageUrl}
     96              src=${this.mainImageUrl}
     97            />
     98          </div>
     99          <div class="main" part="main">
    100            <h2
    101              part="header"
    102              id="header"
    103              class="header heading-large"
    104              ?hidden=${!this.headerLabel}
    105            >
    106              <span
    107                data-l10n-id=${this.headerLabel}
    108                data-l10n-args=${JSON.stringify(this.headerArgs)}
    109              >
    110              </span>
    111            </h2>
    112            <span id="description">
    113              ${repeat(
    114                this.descriptionLabels,
    115                descLabel => descLabel,
    116                (descLabel, index) =>
    117                  html`<p
    118                    class=${classMap({
    119                      description: true,
    120                      secondary: index !== 0,
    121                    })}
    122                    data-l10n-id=${descLabel}
    123                    @click=${this.openLinkInParentWindow &&
    124                    this.linkActionHandler}
    125                    @keydown=${this.openLinkInParentWindow &&
    126                    this.linkActionHandler}
    127                  >
    128                    ${this.linkTemplate(this.descriptionLink)}
    129                  </p>`
    130              )}
    131            </span>
    132            <slot name="primary-action"></slot>
    133          </div>
    134        </div>
    135      </card-container>
    136    `;
    137  }
    138 
    139  linkActionHandler(e) {
    140    const shouldNavigate =
    141      (e.type == "click" && !e.altKey) ||
    142      (e.type == "keydown" && e.code == "Enter") ||
    143      (e.type == "keydown" && e.code == "Space");
    144    if (shouldNavigate && e.target.href) {
    145      navigateToLink(e, e.target.href);
    146      e.preventDefault();
    147    }
    148  }
    149 }
    150 customElements.define("fxview-empty-state", FxviewEmptyState);