commit 13df30dc70933d67e2529d05cca5c1ed24c46d18
parent fb40638bf7baee173d13c948ed397bf66c0d6215
Author: hannajones <hjones@mozilla.com>
Date: Mon, 20 Oct 2025 20:41:44 +0000
Bug 1971835 - Part 1: create an empty state component r=akulyk
Differential Revision: https://phabricator.services.mozilla.com/D268765
Diffstat:
5 files changed, 180 insertions(+), 0 deletions(-)
diff --git a/browser/components/preferences/jar.mn b/browser/components/preferences/jar.mn
@@ -24,6 +24,8 @@ browser.jar:
content/browser/preferences/web-appearance-dark.svg
content/browser/preferences/web-appearance-light.svg
content/browser/preferences/widgets/dialog-button.mjs (widgets/dialog-button/dialog-button.mjs)
+ content/browser/preferences/widgets/placeholder-message.mjs (widgets/placeholder-message/placeholder-message.mjs)
+ content/browser/preferences/widgets/placeholder-message.css (widgets/placeholder-message/placeholder-message.css)
content/browser/preferences/widgets/nav-notice.mjs (widgets/nav-notice/nav-notice.mjs)
content/browser/preferences/widgets/nav-notice.css (widgets/nav-notice/nav-notice.css)
content/browser/preferences/widgets/setting-control.css (widgets/setting-control/setting-control.css)
diff --git a/browser/components/preferences/preferences.xhtml b/browser/components/preferences/preferences.xhtml
@@ -91,6 +91,7 @@
<script src="chrome://browser/content/migration/migration-wizard.mjs" type="module"></script>
<script type="module" src="chrome://browser/content/backup/backup-settings.mjs"></script>
<script type="module" src="chrome://browser/content/preferences/widgets/dialog-button.mjs"></script>
+ <script type="module" src="chrome://browser/content/preferences/widgets/placeholder-message.mjs"></script>
<script type="module" src="chrome://browser/content/preferences/widgets/nav-notice.mjs"></script>
<script type="module" src="chrome://browser/content/preferences/widgets/setting-pane.mjs"></script>
<script type="module" src="chrome://browser/content/preferences/widgets/setting-group.mjs"></script>
diff --git a/browser/components/preferences/widgets/placeholder-message/placeholder-message.css b/browser/components/preferences/widgets/placeholder-message/placeholder-message.css
@@ -0,0 +1,36 @@
+/* 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/. */
+
+moz-box-item {
+ --box-padding: var(--space-xxlarge);
+}
+
+.placeholder-container {
+ gap: var(--space-large);
+}
+
+.placeholder-container,
+.text-container {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.text-container {
+ gap: var(--space-xsmall);
+ text-align: center;
+}
+
+img {
+ max-width: 160px;
+}
+
+.label:has(+ .support-link),
+.description:has(+ .support-link) {
+ margin-inline-end: var(--space-xsmall);
+}
+
+.description {
+ color: var(--text-color-deemphasized);
+}
diff --git a/browser/components/preferences/widgets/placeholder-message/placeholder-message.mjs b/browser/components/preferences/widgets/placeholder-message/placeholder-message.mjs
@@ -0,0 +1,88 @@
+/* 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 { MozLitElement } from "chrome://global/content/lit-utils.mjs";
+import { html } from "chrome://global/content/vendor/lit.all.mjs";
+
+class PlaceholderMessage extends MozLitElement {
+ static properties = {
+ imageSrc: { type: String },
+ label: { type: String, fluent: true },
+ description: { type: String, fluent: true },
+ supportPage: { type: String, attribute: "support-page" },
+ };
+
+ constructor() {
+ super();
+
+ /** @type {string} */
+ this.imageSrc = "";
+
+ /** @type {string} */
+ this.label = "";
+
+ /** @type {string} */
+ this.description = "";
+
+ /** @type {string} */
+ this.supportPage = "";
+ }
+
+ labelTemplate() {
+ if (!this.label) {
+ return "";
+ }
+ return html`<div class="label-wrapper">
+ <span class="label heading-medium" id="label">${this.label}</span>${!this
+ .description
+ ? this.supportLinkTemplate()
+ : ""}
+ </div>`;
+ }
+
+ descriptionTemplate() {
+ if (!this.description) {
+ return "";
+ }
+ return html`<div class="description-wrapper">
+ <span class="description" id="description"> ${this.description}</span
+ >${this.supportLinkTemplate()}
+ </div>`;
+ }
+
+ supportLinkTemplate() {
+ if (!this.supportPage) {
+ return "";
+ }
+ return html`<a
+ is="moz-support-link"
+ class="support-link"
+ support-page=${this.supportPage}
+ part="support-link"
+ aria-describedby="label description"
+ ></a>`;
+ }
+
+ render() {
+ return html`
+ <link
+ rel="stylesheet"
+ href="chrome://browser/content/preferences/widgets/placeholder-message.css"
+ />
+ <link
+ rel="stylesheet"
+ href="chrome://global/skin/design-system/text-and-typography.css"
+ />
+ <moz-box-item>
+ <div class="placeholder-container">
+ <img src=${this.imageSrc} role="presentation" />
+ <div class="text-container">
+ ${this.labelTemplate()} ${this.descriptionTemplate()}
+ </div>
+ </div>
+ </moz-box-item>
+ `;
+ }
+}
+customElements.define("placeholder-message", PlaceholderMessage);
diff --git a/browser/components/preferences/widgets/placeholder-message/placeholder-message.stories.mjs b/browser/components/preferences/widgets/placeholder-message/placeholder-message.stories.mjs
@@ -0,0 +1,53 @@
+/* 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 } from "chrome://global/content/vendor/lit.all.mjs";
+import "chrome://browser/content/preferences/widgets/placeholder-message.mjs";
+
+export default {
+ title: "Domain-specific UI Widgets/Settings/Placeholder Message",
+ component: "placeholder-message",
+ argTypes: {
+ l10nId: {
+ options: [
+ "placeholder-message-label",
+ "placeholder-message-label-description",
+ ],
+ control: { type: "select" },
+ },
+ },
+ parameters: {
+ status: "in-development",
+ fluent: `
+placeholder-message-label =
+ .label = You are not signed in
+placeholder-message-label-description =
+ .label = You are not signed in
+ .description = With a Mozilla account, you can sync your bookmarks, history, tabs, passwords, add-ons, and settings across all your devices.
+ `,
+ },
+};
+
+const Template = ({ imageSrc = "", l10nId = "", supportPage = "" }) => html`
+ <div style="max-width: 500px">
+ <placeholder-message
+ imageSrc=${ifDefined(imageSrc)}
+ data-l10n-id=${l10nId}
+ support-page=${ifDefined(supportPage)}
+ ></placeholder-message>
+ </div>
+`;
+
+export const Default = Template.bind({});
+Default.args = {
+ imageSrc: "chrome://global/skin/illustrations/security-error.svg",
+ l10nId: "placeholder-message-label-description",
+ supportPage: "",
+};
+
+export const WithSupportPage = Template.bind({});
+WithSupportPage.args = {
+ ...Default.args,
+ supportPage: "test",
+};