Bug 1944627 - update sidebar button checked state for non-revamped sidebar cases...
[gecko.git] / browser / components / firefoxview / card-container.mjs
blobd72b4a936482e75134c1ee8091bbb24b723442a8
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 import {
6   classMap,
7   html,
8   ifDefined,
9   when,
10 } from "chrome://global/content/vendor/lit.all.mjs";
11 import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
13 /**
14  * A collapsible card container to be used throughout Firefox View
15  *
16  * @property {string} sectionLabel - The aria-label used for the section landmark if the header is hidden with hideHeader
17  * @property {boolean} hideHeader - Optional property given if the card container should not display a header
18  * @property {boolean} isEmptyState - Optional property given if the card is used within an empty state
19  * @property {boolean} isInnerCard - Optional property given if the card a nested card within another card and given a border rather than box-shadow
20  * @property {boolean} preserveCollapseState - Whether or not the expanded/collapsed state should persist
21  * @property {string} shortPageName - Page name that the 'View all' link will navigate to and the preserveCollapseState pref will use
22  * @property {boolean} showViewAll - True if you need to display a 'View all' header link to navigate
23  * @property {boolean} toggleDisabled - Optional property given if the card container should not be collapsible
24  * @property {boolean} removeBlockEndMargin - True if you need to remove the block end margin on the card container
25  */
26 class CardContainer extends MozLitElement {
27   constructor() {
28     super();
29     this.initiallyExpanded = true;
30     this.isExpanded = false;
31     this.visible = false;
32   }
34   static properties = {
35     sectionLabel: { type: String },
36     hideHeader: { type: Boolean },
37     isExpanded: { type: Boolean },
38     isEmptyState: { type: Boolean },
39     isInnerCard: { type: Boolean },
40     preserveCollapseState: { type: Boolean },
41     shortPageName: { type: String },
42     showViewAll: { type: Boolean },
43     toggleDisabled: { type: Boolean },
44     removeBlockEndMargin: { type: Boolean },
45     visible: { type: Boolean },
46   };
48   static queries = {
49     detailsEl: "details",
50     mainSlot: "slot[name=main]",
51     summaryEl: "summary",
52     viewAllLink: ".view-all-link",
53   };
55   get detailsExpanded() {
56     return this.detailsEl.hasAttribute("open");
57   }
59   get detailsOpenPrefValue() {
60     const prefName = this.shortPageName
61       ? `browser.tabs.firefox-view.ui-state.${this.shortPageName}.open`
62       : null;
63     if (prefName && Services.prefs.prefHasUserValue(prefName)) {
64       return Services.prefs.getBoolPref(prefName);
65     }
66     return null;
67   }
69   connectedCallback() {
70     super.connectedCallback();
71     this.isExpanded = this.detailsOpenPrefValue ?? this.initiallyExpanded;
72   }
74   onToggleContainer() {
75     if (this.isExpanded == this.detailsExpanded) {
76       return;
77     }
78     this.isExpanded = this.detailsExpanded;
80     this.updateTabLists();
82     if (!this.shortPageName) {
83       return;
84     }
86     if (this.preserveCollapseState) {
87       const prefName = this.shortPageName
88         ? `browser.tabs.firefox-view.ui-state.${this.shortPageName}.open`
89         : null;
90       Services.prefs.setBoolPref(prefName, this.isExpanded);
91     }
93     // Record telemetry
94     Glean.firefoxviewNext[
95       `card${this.isExpanded ? "Expanded" : "Collapsed"}CardContainer`
96     ].record({
97       data_type: this.shortPageName,
98     });
99   }
101   viewAllClicked() {
102     this.dispatchEvent(
103       new CustomEvent("card-container-view-all", {
104         bubbles: true,
105         composed: true,
106       })
107     );
108   }
110   willUpdate(changes) {
111     if (changes.has("visible")) {
112       this.updateTabLists();
113     }
114   }
116   updateTabLists() {
117     let tabLists = this.querySelectorAll(
118       "fxview-tab-list, opentabs-tab-list, syncedtabs-tab-list"
119     );
120     if (tabLists) {
121       tabLists.forEach(tabList => {
122         tabList.updatesPaused = !this.visible || !this.isExpanded;
123       });
124     }
125   }
127   render() {
128     return html`
129       <link
130         rel="stylesheet"
131         href="chrome://browser/content/firefoxview/card-container.css"
132       />
133       ${when(
134         this.toggleDisabled,
135         () =>
136           html`<div
137             class=${classMap({
138               "card-container": true,
139               inner: this.isInnerCard,
140               "empty-state": this.isEmptyState && !this.isInnerCard,
141             })}
142           >
143             <span
144               id="header"
145               class="card-container-header"
146               ?hidden=${ifDefined(this.hideHeader)}
147               toggleDisabled
148               ?withViewAll=${this.showViewAll}
149             >
150               <slot name="header"></slot>
151               <slot name="secondary-header"></slot>
152             </span>
153             <a
154               href="about:firefoxview#${this.shortPageName}"
155               @click=${this.viewAllClicked}
156               class="view-all-link"
157               data-l10n-id="firefoxview-view-all-link"
158               ?hidden=${!this.showViewAll}
159             ></a>
160             <slot name="main"></slot>
161             <slot name="footer" class="card-container-footer"></slot>
162           </div>`,
163         () =>
164           html`<details
165             class=${classMap({
166               "card-container": true,
167               inner: this.isInnerCard,
168               "empty-state": this.isEmptyState && !this.isInnerCard,
169             })}
170             ?open=${this.isExpanded}
171             ?isOpenTabsView=${this.removeBlockEndMargin}
172             @toggle=${this.onToggleContainer}
173             role=${this.isInnerCard ? "presentation" : "group"}
174           >
175             <summary
176               class="card-container-header"
177               ?hidden=${ifDefined(this.hideHeader)}
178               ?withViewAll=${this.showViewAll}
179             >
180               <span
181                 class="icon chevron-icon"
182                 role="presentation"
183                 data-l10n-id="firefoxview-collapse-button-${this.isExpanded
184                   ? "hide"
185                   : "show"}"
186               ></span>
187               <slot name="header"></slot>
188             </summary>
189             <a
190               href="about:firefoxview#${this.shortPageName}"
191               @click=${this.viewAllClicked}
192               class="view-all-link"
193               data-l10n-id="firefoxview-view-all-link"
194               ?hidden=${!this.showViewAll}
195             ></a>
196             <slot name="main"></slot>
197             <slot name="footer" class="card-container-footer"></slot>
198           </details>`
199       )}
200     `;
201   }
203 customElements.define("card-container", CardContainer);