@@ -21,6 +21,68 @@ document.querySelectorAll(".code-group-button").forEach((button) => {
2121 } ) ;
2222} ) ;
2323
24+ function initIndexSubsections ( ) {
25+ const panels = Array . from ( document . querySelectorAll ( ".index-subsections" ) ) ;
26+ const content = panels [ 0 ] ?. closest ( ".content" ) ;
27+ if ( ! panels . length || ! content ) return ;
28+
29+ const hoverQuery = globalThis . matchMedia ( "(hover: hover) and (pointer: fine)" ) ;
30+ const entries = panels . map ( ( panel , index ) => {
31+ const item = panel . parentElement ;
32+ const list = panel . querySelector ( ":scope > ul" ) ;
33+ const link = item ?. querySelector ( ":scope > a, :scope > p > a" ) ;
34+ if ( ! item || ! list || ! link ) return null ;
35+
36+ const title = list . getAttribute ( "aria-label" ) ?. replace ( / ^ S e c t i o n s i n / , "" ) || link . textContent . trim ( ) ;
37+ const button = document . createElement ( "button" ) ;
38+ const panelId = `index-subsections-${ index + 1 } ` ;
39+
40+ panel . id = panelId ;
41+ item . classList . add ( "index-item-collapsible" ) ;
42+ button . type = "button" ;
43+ button . className = "index-subsection-toggle" ;
44+ button . setAttribute ( "aria-controls" , panelId ) ;
45+ button . innerHTML = '<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M3 5.5l5 5 5-5" /></svg>' ;
46+ link . after ( button ) ;
47+
48+ const entry = { button, item, panel, title } ;
49+ button . addEventListener ( "click" , ( ) => {
50+ if ( ! hoverQuery . matches ) setOpen ( entry , ! item . classList . contains ( "is-open" ) ) ;
51+ } ) ;
52+ return entry ;
53+ } ) . filter ( Boolean ) ;
54+
55+ function setOpen ( entry , open ) {
56+ entry . item . classList . toggle ( "is-open" , open ) ;
57+ entry . panel . inert = ! open ;
58+ entry . panel . setAttribute ( "aria-hidden" , String ( ! open ) ) ;
59+ entry . button . setAttribute ( "aria-expanded" , String ( open ) ) ;
60+ entry . button . setAttribute ( "aria-label" , `${ open ? "Hide" : "Show" } sections in ${ entry . title } ` ) ;
61+ }
62+
63+ function syncInputMode ( ) {
64+ for ( const entry of entries ) {
65+ entry . item . classList . remove ( "is-open" ) ;
66+ if ( hoverQuery . matches ) {
67+ entry . panel . inert = false ;
68+ entry . panel . removeAttribute ( "aria-hidden" ) ;
69+ entry . button . tabIndex = - 1 ;
70+ entry . button . setAttribute ( "aria-hidden" , "true" ) ;
71+ entry . button . removeAttribute ( "aria-expanded" ) ;
72+ entry . button . removeAttribute ( "aria-label" ) ;
73+ } else {
74+ entry . button . tabIndex = 0 ;
75+ entry . button . removeAttribute ( "aria-hidden" ) ;
76+ setOpen ( entry , false ) ;
77+ }
78+ }
79+ }
80+
81+ syncInputMode ( ) ;
82+ content . classList . add ( "index-subsections-enhanced" ) ;
83+ hoverQuery . addEventListener ( "change" , syncInputMode ) ;
84+ }
85+
2486function initToc ( ) {
2587 const toc = document . querySelector ( ".toc" ) ;
2688 const viewport = toc ?. querySelector ( ".toc-list-wrap" ) ;
@@ -376,4 +438,5 @@ function initToc() {
376438 if ( ! activateHashEntry ( ) ) updateActive ( ) ;
377439}
378440
441+ initIndexSubsections ( ) ;
379442initToc ( ) ;
0 commit comments