class AccordionItem extends HTMLElement {
static get observedAttributes() {
return ['title'];
}
#title = '';
#collapsed = true;
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
this.update();
this.shadowRoot.addEventListener('click', this.toggle.bind(this));
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'title') {
this.#title = newValue;
}
this.update();
}
toggle() {
this.#collapsed = !this.#collapsed;
this.update();
// Dispatch a custom event to notify the parent AccordionElement
const event = new CustomEvent('accordion-item-toggle', {
bubbles: true,
detail: {
collapsed: this.#collapsed,
item: this,
},
});
this.dispatchEvent(event);
}
update() {
this.shadowRoot.innerHTML = `
`;
}
}
class AccordionElement extends HTMLElement {
#activeItem = null;
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = '';
this.addEventListener('accordion-item-toggle', this.handleItemToggle.bind(this));
}
handleItemToggle(event) {
const { collapsed, item } = event.detail;
// If the active item is different from the toggled item, collapse the active item
if (this.#activeItem && this.#activeItem !== item && !collapsed) {
this.#activeItem.toggle();
}
// Update the active item
if (!collapsed) {
this.#activeItem = item;
} else if (this.#activeItem === item) {
this.#activeItem = null;
}
}
}
customElements.define('accordion-item', AccordionItem);
customElements.define('accordion-element', AccordionElement);