inspector.js (2365B)
1 // A docked inspector on wide screens, an accessible modal sheet on phones. 2 export function setupInspector() { 3 const panel = document.getElementById('settings-panel'), toggle = document.getElementById('settings-toggle'); 4 const close = document.getElementById('settings-close'), backdrop = document.getElementById('settings-backdrop'); 5 const body = document.getElementById('editor-body'), mobile = matchMedia('(max-width:740px)'); 6 const background = [...document.querySelectorAll('[data-inspector-background]')]; 7 let open = false; 8 function layout() { 9 panel.hidden = !open; 10 backdrop.hidden = !open || !mobile.matches; 11 body.classList.toggle('settings-open', open); 12 toggle.setAttribute('aria-expanded', String(open)); 13 panel.setAttribute('role', mobile.matches ? 'dialog' : 'region'); 14 if (mobile.matches && open) 15 panel.setAttribute('aria-modal', 'true'); 16 else 17 panel.removeAttribute('aria-modal'); 18 for (const element of background) 19 element.inert = open && mobile.matches; 20 document.body.classList.toggle('inspector-modal', open && mobile.matches); 21 if (open && mobile.matches && !panel.contains(document.activeElement)) 22 close.focus(); 23 } 24 function hide() { open = false; layout(); toggle.focus(); } 25 toggle.onclick = () => { if (open) 26 hide(); 27 else { 28 open = true; 29 layout(); 30 close.focus(); 31 } }; 32 close.onclick = backdrop.onclick = hide; 33 mobile.addEventListener('change', layout); 34 panel.addEventListener('keydown', event => { 35 if (event.key === 'Escape') { 36 event.preventDefault(); 37 hide(); 38 } 39 if (event.key !== 'Tab' || !mobile.matches) 40 return; 41 const items = [...panel.querySelectorAll('button,input,select,textarea,a[href],summary,[tabindex="0"]')] 42 .filter(e => !e.hasAttribute('disabled') && e.getClientRects().length > 0); 43 const first = items[0], last = items.at(-1); 44 if (event.shiftKey && document.activeElement === first) { 45 event.preventDefault(); 46 last?.focus(); 47 } 48 else if (!event.shiftKey && document.activeElement === last) { 49 event.preventDefault(); 50 first?.focus(); 51 } 52 }); 53 layout(); 54 }