/** * Content Tabs Component * Tabbed interface for displaying different content sections */ class ContentTabs extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); this.activeTab = 0; } connectedCallback() { this.render(); this.setupEventListeners(); } get tabs() { const tabsAttr = this.getAttribute("tabs"); return tabsAttr ? tabsAttr.split(",").map((t) => t.trim()) : []; } setupEventListeners() { const tabButtons = this.shadowRoot.querySelectorAll(".tab-button"); tabButtons.forEach((button, index) => { button.addEventListener("click", () => { this.setActiveTab(index); }); }); } setActiveTab(index) { this.activeTab = index; this.updateTabs(); this.dispatchEvent( new CustomEvent("tab-change", { bubbles: true, composed: true, detail: { index, tab: this.tabs[index] }, }) ); } updateTabs() { // Update tab buttons const tabButtons = this.shadowRoot.querySelectorAll(".tab-button"); tabButtons.forEach((button, index) => { button.classList.toggle("active", index === this.activeTab); }); // Update panels const panels = this.querySelectorAll("[slot^='panel-']"); panels.forEach((panel, index) => { panel.style.display = index === this.activeTab ? "block" : "none"; }); } render() { const tabsHtml = this.tabs .map( (tab, index) => ` ` ) .join(""); this.shadowRoot.innerHTML = `
${tabsHtml}
`; // Initialize panel visibility setTimeout(() => this.updateTabs(), 0); } } customElements.define("content-tabs", ContentTabs);