class CustomAccordion extends HTMLElement {
static get observedAttributes() {
return ['title', 'initially-open'];
}
constructor() {
super();
this.isOpen = this.getAttribute('initially-open') === 'true';
this.title = this.getAttribute('title') || 'Titre de l\'accordéon';
}
connectedCallback() {
this.attachShadow({ mode: 'open' });
this.render();
this.initEventListeners();
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'title' && oldValue !== newValue) {
const titleElement = this.shadowRoot.querySelector('.accordion-title');
if (titleElement) {
titleElement.textContent = newValue;
}
}
if (name === 'initially-open' && oldValue !== newValue) {
this.isOpen = newValue === 'true';
this.toggleContent();
}
}
render() {
this.shadowRoot.innerHTML = `
`;
// Initialiser les icônes Feather
if (typeof feather !== 'undefined') {
feather.replace();
}
}
initEventListeners() {
const header = this.shadowRoot.querySelector('#accordionHeader');
const icon = this.shadowRoot.querySelector('#accordionIcon i');
header.addEventListener('click', () => {
this.toggle();
// Animation de l'icône
if (icon) {
if (this.isOpen) {
icon.setAttribute('data-feather', 'chevron-up');
} else {
icon.setAttribute('data-feather', 'chevron-down');
}
feather.replace();
}
});
// Animation d'entrée
setTimeout(() => {
const item = this.shadowRoot.querySelector('.accordion-item');
item.style.opacity = '0';
item.style.transform = 'translateY(10px)';
item.style.transition = 'all 0.4s ease';
setTimeout(() => {
item.style.opacity = '1';
item.style.transform = 'translateY(0)';
}, 100);
}, 100);
}
toggle() {
this.isOpen = !this.isOpen;
const content = this.shadowRoot.querySelector('#accordionContent');
const item = this.shadowRoot.querySelector('.accordion-item');
const icon = this.shadowRoot.querySelector('#accordionIcon i');
if (this.isOpen) {
content.classList.add('open');
item.classList.add('open');
if (icon) {
icon.style.transform = 'rotate(180deg)';
}
// Émettre un événement personnalisé
this.dispatchEvent(new CustomEvent('accordion-open', {
detail: { title: this.title },
bubbles: true,
composed: true
}));
} else {
content.classList.remove('open');
item.classList.remove('open');
if (icon) {
icon.style.transform = 'rotate(0)';
}
this.dispatchEvent(new CustomEvent('accordion-close', {
detail: { title: this.title },
bubbles: true,
composed: true
}));
}
}
open() {
if (!this.isOpen) {
this.toggle();
}
}
close() {
if (this.isOpen) {
this.toggle();
}
}
// Méthode publique pour initialiser l'état
init() {
this.toggleContent();
}
toggleContent() {
const content = this.shadowRoot.querySelector('#accordionContent');
const item = this.shadowRoot.querySelector('.accordion-item');
if (this.isOpen) {
content?.classList.add('open');
item?.classList.add('open');
} else {
content?.classList.remove('open');
item?.classList.remove('open');
}
}
}
customElements.define('custom-accordion', CustomAccordion);