Skip to content

Commit 75475db

Browse files
authored
Update PicoTabs.js
Closes #31 Multiple tabs, and nested tabs are working with this update.
1 parent a4ca1dc commit 75475db

File tree

1 file changed

+36
-29
lines changed

1 file changed

+36
-29
lines changed

docs/js/PicoTabs.js

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -29,68 +29,75 @@ document.addEventListener("DOMContentLoaded", () => {
2929

3030
class PicoTabs {
3131
constructor(tabListContainerSelector) {
32-
this.tabListContainer = document.querySelector(tabListContainerSelector);
33-
// Check if tablist element exists on the page
34-
if (!this.tabListContainer) {
35-
console.warn(`No element with ${tabListContainerSelector} found on the page.`);
32+
this.tabLists = document.querySelectorAll(tabListContainerSelector);
33+
34+
// Proceed only if tablists are found
35+
if (this.tabLists.length === 0) {
36+
console.warn(`No elements with ${tabListContainerSelector} found on the page.`);
3637
return;
3738
}
3839

39-
this.tabs = this.tabListContainer.querySelectorAll('[role="tab"]');
40-
this.panels = document.querySelectorAll('[role="tabpanel"]');
40+
this.tabLists.forEach((tabList) => {
41+
const tabs = Array.from(tabList.querySelectorAll('[role="tab"]'));
42+
const panels = Array.from(tabList.querySelectorAll('[role="tabpanel"]'));
4143

42-
// Proceed only if tabs and panels are found
43-
if (this.tabs.length === 0 || this.panels.length === 0) {
44-
console.warn("No tabs or panels found, initialization aborted.");
45-
return;
46-
}
44+
// Filter out nested tabs and panels
45+
const rootTabs = tabs.filter((tab) => tab.closest(tabListContainerSelector) === tabList);
46+
const rootPanels = panels.filter((panel) => panel.closest(tabListContainerSelector) === tabList);
4747

48-
this.init();
48+
// Proceed only if root tabs and panels are found
49+
if (rootTabs.length === 0 || rootPanels.length === 0) {
50+
console.warn("No root tabs or panels found in a tablist, skipping initialization.");
51+
return;
52+
}
53+
54+
this.init(tabList, rootTabs, rootPanels);
55+
});
4956
}
5057

51-
init() {
52-
this.tabs.forEach((tab, index) => {
53-
tab.addEventListener("click", () => this.activateTab(index));
54-
tab.addEventListener("keydown", (e) => this.handleKeyDown(e, index));
58+
init(tabList, tabs, panels) {
59+
tabs.forEach((tab, index) => {
60+
tab.addEventListener("click", () => this.activateTab(tabs, panels, index));
61+
tab.addEventListener("keydown", (e) => this.handleKeyDown(e, tabs, panels, index));
5562
});
5663
}
5764

5865
// Activate a tab and corresponding panel
59-
activateTab(index) {
60-
// Reset all tabs and panels
61-
this.tabs.forEach((tab, i) => {
66+
activateTab(tabs, panels, index) {
67+
// Reset all tabs and panels within the current tablist
68+
tabs.forEach((tab, i) => {
6269
tab.setAttribute("aria-selected", "false");
6370
tab.setAttribute("tabindex", "-1");
64-
this.panels[i].setAttribute("hidden", "true");
71+
panels[i].setAttribute("hidden", "true");
6572
});
6673

6774
// Activate the specified tab
68-
this.tabs[index].setAttribute("aria-selected", "true");
69-
this.tabs[index].setAttribute("tabindex", "0");
70-
this.panels[index].removeAttribute("hidden");
75+
tabs[index].setAttribute("aria-selected", "true");
76+
tabs[index].setAttribute("tabindex", "0");
77+
panels[index].removeAttribute("hidden");
7178

7279
// Focus the activated tab
73-
this.tabs[index].focus();
80+
tabs[index].focus();
7481
}
7582

7683
// Handle keyboard navigation
77-
handleKeyDown(event, currentIndex) {
84+
handleKeyDown(event, tabs, panels, currentIndex) {
7885
switch (event.key) {
7986
case "ArrowLeft":
8087
event.preventDefault();
81-
this.activateTab((currentIndex - 1 + this.tabs.length) % this.tabs.length);
88+
this.activateTab(tabs, panels, (currentIndex - 1 + tabs.length) % tabs.length);
8289
break;
8390
case "ArrowRight":
8491
event.preventDefault();
85-
this.activateTab((currentIndex + 1) % this.tabs.length);
92+
this.activateTab(tabs, panels, (currentIndex + 1) % tabs.length);
8693
break;
8794
case "Home":
8895
event.preventDefault();
89-
this.activateTab(0);
96+
this.activateTab(tabs, panels, 0);
9097
break;
9198
case "End":
9299
event.preventDefault();
93-
this.activateTab(this.tabs.length - 1);
100+
this.activateTab(tabs, panels, tabs.length - 1);
94101
break;
95102
default:
96103
break;

0 commit comments

Comments
 (0)