Source code

Revision control

Copy as Markdown

Other Tools

/* -*- 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,
when,
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} icon - (optional) A flag to indicate the header should include an icon
* @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 },
icon: { type: Boolean },
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">
${when(
this.type == "accordion",
() => html`<div class="chevron-icon"></div>`
)}
${when(
this.icon,
() =>
html`<div part="icon" id="heading-icon" role="presentation"></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"
/>
<article
class="moz-card"
aria-labelledby=${ifDefined(this.heading ? "heading" : undefined)}
>
${this.cardTemplate()}
</article>
`;
}
}
customElements.define("moz-card", MozCard);