summaryrefslogtreecommitdiffstats
path: root/toolkit/content/widgets/moz-card/moz-card.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/content/widgets/moz-card/moz-card.mjs')
-rw-r--r--toolkit/content/widgets/moz-card/moz-card.mjs112
1 files changed, 112 insertions, 0 deletions
diff --git a/toolkit/content/widgets/moz-card/moz-card.mjs b/toolkit/content/widgets/moz-card/moz-card.mjs
new file mode 100644
index 0000000000..2bd6e0f987
--- /dev/null
+++ b/toolkit/content/widgets/moz-card/moz-card.mjs
@@ -0,0 +1,112 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
+ * 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 { MozLitElement } from "chrome://global/content/lit-utils.mjs";
+
+/**
+ * Cards contain content and actions about a single subject.
+ * There are two card types:
+ * The default type where no type attribute is required and the card
+ * will have no extra functionality.
+ *
+ * The "accordion" type will initially not show any content. The card
+ * will contain an arrow to expand the card so that all of the content
+ * is visible.
+ *
+ *
+ * @property {string} heading - The heading text that will be used for the card.
+ * @property {string} type - (optional) The type of card. No type specified
+ * will be the default card. The other available type is "accordion"
+ * @slot content - The content to show inside of the card.
+ */
+export default class MozCard extends MozLitElement {
+ static queries = {
+ detailsEl: "#moz-card-details",
+ headingEl: "#heading",
+ contentSlotEl: "#content",
+ };
+
+ static properties = {
+ heading: { type: String },
+ type: { type: String, reflect: true },
+ expanded: { type: Boolean },
+ };
+
+ constructor() {
+ super();
+ this.expanded = false;
+ this.type = "default";
+ }
+
+ headingTemplate() {
+ if (!this.heading) {
+ return "";
+ }
+ return html`
+ <div id="heading-wrapper">
+ ${this.type == "accordion"
+ ? html` <div class="chevron-icon"></div>`
+ : ""}
+ <span id="heading">${this.heading}</span>
+ </div>
+ `;
+ }
+
+ cardTemplate() {
+ if (this.type === "accordion") {
+ return html`
+ <details id="moz-card-details">
+ <summary>${this.headingTemplate()}</summary>
+ <div id="content"><slot></slot></div>
+ </details>
+ `;
+ }
+
+ return html`
+ ${this.headingTemplate()}
+ <div id="content" aria-describedby="content">
+ <slot></slot>
+ </div>
+ `;
+ }
+ /**
+ * Handles the click event on the chevron icon.
+ *
+ * Without this, the click event would be passed to
+ * toggleDetails which would force the details element
+ * to stay open.
+ *
+ * @memberof MozCard
+ */
+ onDetailsClick() {
+ this.toggleDetails();
+ }
+
+ /**
+ * @param {boolean} force - Used to force open or force close the
+ * details element.
+ * @memberof MozCard
+ */
+ toggleDetails(force) {
+ this.detailsEl.open = force ?? !this.detailsEl.open;
+ }
+
+ render() {
+ return html`
+ <link
+ rel="stylesheet"
+ href="chrome://global/content/elements/moz-card.css"
+ />
+ <article
+ class="moz-card"
+ aria-labelledby=${ifDefined(this.heading ? "heading" : undefined)}
+ >
+ ${this.cardTemplate()}
+ </article>
+ `;
+ }
+}
+customElements.define("moz-card", MozCard);