tabs.js (1636B)
1 const tabs = [...document.querySelectorAll('[role="tab"]')]; 2 export function activePane() { 3 return (tabs.find(tab => tab.getAttribute('aria-selected') === 'true')?.dataset['pane'] ?? 'how'); 4 } 5 function activate(pane, focus = false) { 6 const changed = activePane() !== pane; 7 for (const tab of tabs) { 8 const selected = tab.dataset['pane'] === pane; 9 tab.setAttribute('aria-selected', String(selected)); 10 tab.tabIndex = selected ? 0 : -1; 11 const panel = document.getElementById(tab.getAttribute('aria-controls')); 12 panel.classList.toggle('is-active', selected); 13 panel.inert = !selected; 14 panel.setAttribute('aria-hidden', String(!selected)); 15 if (selected && focus) 16 tab.focus(); 17 } 18 if (changed) 19 window.dispatchEvent(new CustomEvent('pane-change', { detail: pane })); 20 } 21 for (const [index, tab] of tabs.entries()) { 22 tab.onclick = () => activate(tab.dataset['pane']); 23 tab.onkeydown = event => { 24 const target = event.key === 'ArrowRight' ? (index + 1) % tabs.length 25 : event.key === 'ArrowLeft' ? (index + tabs.length - 1) % tabs.length 26 : event.key === 'Home' ? 0 : event.key === 'End' ? tabs.length - 1 : undefined; 27 if (target !== undefined) { 28 event.preventDefault(); 29 activate(tabs[target].dataset['pane'], true); 30 } 31 }; 32 } 33 for (const link of document.querySelectorAll('a[data-open-pane]')) 34 link.onclick = () => { 35 activate(link.dataset['openPane']); 36 }; 37 // Selection links are metadata, not permission to enter an execution pane. 38 activate('how');