Files
milinda-pitch/js/components/footer-accordion-item.js
rubberducky 3dbe404443 feature/book-page (#4)
Co-authored-by: Tim Rijkse <trijkse@gmail.com>
Reviewed-on: #4
2026-01-16 08:46:03 +00:00

113 lines
2.7 KiB
JavaScript

/**
* Footer Accordion Item Component
* Expandable accordion item for footer navigation
*/
class FooterAccordionItem extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
this._expanded = false;
}
static get observedAttributes() {
return ["title"];
}
connectedCallback() {
this.render();
this.setupEventListeners();
}
attributeChangedCallback() {
this.render();
this.setupEventListeners();
}
setupEventListeners() {
const header = this.shadowRoot.querySelector(".accordion-header");
if (header) {
header.addEventListener("click", () => this.toggle());
}
}
toggle() {
this._expanded = !this._expanded;
const content = this.shadowRoot.querySelector(".accordion-content");
const icon = this.shadowRoot.querySelector(".accordion-icon");
if (content) {
content.classList.toggle("expanded", this._expanded);
}
if (icon) {
icon.classList.toggle("rotated", this._expanded);
}
}
render() {
const title = this.getAttribute("title") || "";
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
}
.accordion-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--spacing-lg, 1.5rem) 0;
cursor: pointer;
user-select: none;
}
.accordion-header:hover {
opacity: 0.9;
}
.accordion-title {
font-size: var(--font-size-base, 1rem);
font-weight: 400;
color: var(--color-text-inverse, #ffffff);
margin: 0;
}
.accordion-icon {
display: inline-flex;
color: var(--color-text-inverse, #ffffff);
transition: transform var(--transition-fast, 150ms ease);
}
.accordion-icon.rotated {
transform: rotate(180deg);
}
.accordion-content {
max-height: 0;
overflow: hidden;
transition: max-height var(--transition-normal, 300ms ease), padding var(--transition-normal, 300ms ease);
}
.accordion-content.expanded {
max-height: 500px;
padding-bottom: var(--spacing-lg, 1.5rem);
}
::slotted(*) {
color: var(--color-text-inverse, #ffffff);
}
</style>
<div class="accordion-header">
<h3 class="accordion-title">${title}</h3>
<chevron-down-icon class="accordion-icon" size="24"></chevron-down-icon>
</div>
<div class="accordion-content">
<slot></slot>
</div>
`;
}
}
customElements.define("footer-accordion-item", FooterAccordionItem);