diff options
Diffstat (limited to 'toolkit/content/widgets/moz-card/moz-card.mjs')
-rw-r--r-- | toolkit/content/widgets/moz-card/moz-card.mjs | 112 |
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); |