gecko-dev/browser/components/firefoxview/fxview-empty-state.mjs
Nikki Sharpley 5d28ac8fbb Bug 1886847 - Styling and UI polish for sidebar r=sidebar-reviewers,desktop-theme-reviewers,fxview-reviewers,reusable-components-reviewers,dao,settings-reviewers,tgiles,mconley,jsudiaman,kcochrane
- styled synced tabs and history
- styled sidebar search
- styled customize settings
- added sidebar right icon to customize input

Differential Revision: https://phabricator.services.mozilla.com/D216748
2024-08-02 19:10:14 +00:00

142 lines
5.3 KiB
JavaScript

/* 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/. */
import {
html,
ifDefined,
classMap,
repeat,
} from "chrome://global/content/vendor/lit.all.mjs";
import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
import { navigateToLink } from "chrome://browser/content/firefoxview/helpers.mjs";
/**
* An empty state card to be used throughout Firefox View
*
* @property {string} headerIconUrl - (Optional) The chrome:// url for an icon to be displayed within the header
* @property {string} headerLabel - (Optional) The l10n id for the header text for the empty/error state
* @property {object} headerArgs - (Optional) The l10n args for the header text for the empty/error state
* @property {string} isInnerCard - (Optional) True if the card is displayed within another card and needs a border instead of box shadow
* @property {boolean} isSelectedTab - (Optional) True if the component is the selected navigation tab - defaults to false
* @property {Array} descriptionLabels - (Optional) An array of l10n ids for the secondary description text for the empty/error state
* @property {object} descriptionLink - (Optional) An object describing the l10n name and url needed within a description label
* @property {string} mainImageUrl - (Optional) The chrome:// url for the main image of the empty/error state
* @property {string} errorGrayscale - (Optional) The image should be shown in gray scale
* @property {boolean} openLinkInParentWindow - (Optional) The link, when clicked, should be opened programatically in the parent window.
*/
class FxviewEmptyState extends MozLitElement {
constructor() {
super();
this.isSelectedTab = false;
this.descriptionLabels = [];
this.headerArgs = {};
}
static properties = {
headerLabel: { type: String },
headerArgs: { type: Object },
headerIconUrl: { type: String },
isInnerCard: { type: Boolean },
isSelectedTab: { type: Boolean },
descriptionLabels: { type: Array },
desciptionLink: { type: Object },
mainImageUrl: { type: String },
errorGrayscale: { type: Boolean },
openLinkInParentWindow: { type: Boolean },
};
static queries = {
headerEl: ".header",
descriptionEls: { all: ".description" },
};
linkTemplate(descriptionLink) {
if (!descriptionLink) {
return html``;
}
return html` <a
data-l10n-name=${descriptionLink.name}
href=${descriptionLink.url}
target=${descriptionLink?.sameTarget ? "_self" : "_blank"}
/>`;
}
render() {
return html`
<link
rel="stylesheet"
href="chrome://browser/content/firefoxview/fxview-empty-state.css"
/>
<card-container hideHeader="true" exportparts="image" ?isInnerCard="${
this.isInnerCard
}" id="card-container" isEmptyState="true" role="group" aria-labelledby="header" aria-describedby="description">
<div slot="main" part="container" class=${classMap({
selectedTab: this.isSelectedTab,
imageHidden: !this.mainImageUrl,
})}>
<div class="image-container">
<img class=${classMap({
image: true,
greyscale: this.errorGrayscale,
})}
part="image"
role="presentation"
alt=""
?hidden=${!this.mainImageUrl}
src=${this.mainImageUrl}/>
</div>
<div class="main">
<h2
part="header"
id="header"
class="header heading-large"
?hidden=${!this.headerLabel}
>
<img class="icon info"
data-l10n-id="firefoxview-empty-state-icon"
?hidden=${!this.headerIconUrl}
src=${ifDefined(this.headerIconUrl)}></img>
<span
data-l10n-id="${this.headerLabel}"
data-l10n-args="${JSON.stringify(this.headerArgs)}">
</span>
</h2>
<span id="description">
${repeat(
this.descriptionLabels,
descLabel => descLabel,
(descLabel, index) => html`<p
class=${classMap({
description: true,
secondary: index !== 0,
})}
data-l10n-id="${descLabel}"
@click=${this.openLinkInParentWindow &&
this.linkActionHandler}
@keydown=${this.openLinkInParentWindow &&
this.linkActionHandler}
>
${this.linkTemplate(this.descriptionLink)}
</p>`
)}
</span>
<slot name="primary-action"></slot>
</div>
</div>
</card-container>
`;
}
linkActionHandler(e) {
const shouldNavigate =
(e.type == "click" && !e.altKey) ||
(e.type == "keydown" && e.code == "Enter") ||
(e.type == "keydown" && e.code == "Space");
if (shouldNavigate && e.target.href) {
navigateToLink(e, e.target.href);
e.preventDefault();
}
}
}
customElements.define("fxview-empty-state", FxviewEmptyState);