@@ -29,68 +29,75 @@ document.addEventListener("DOMContentLoaded", () => {
2929
3030class 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