tricu

An interpreted language for exploring Tree Calculus
Log | Files | Refs | README | LICENSE

inspector.ts (2112B)


      1 // A docked inspector on wide screens, an accessible modal sheet on phones.
      2 export function setupInspector(): void {
      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<HTMLElement>('[data-inspector-background]')];
      7   let open = false;
      8   function layout(): void {
      9     panel.hidden = !open; backdrop.hidden = !open || !mobile.matches;
     10     body.classList.toggle('settings-open', open);
     11     toggle.setAttribute('aria-expanded', String(open));
     12     panel.setAttribute('role', mobile.matches ? 'dialog' : 'region');
     13     if (mobile.matches && open) panel.setAttribute('aria-modal', 'true'); else panel.removeAttribute('aria-modal');
     14     for (const element of background) element.inert = open && mobile.matches;
     15     document.body.classList.toggle('inspector-modal', open && mobile.matches);
     16     if (open && mobile.matches && !panel.contains(document.activeElement)) close.focus();
     17   }
     18   function hide(): void { open = false; layout(); toggle.focus(); }
     19   toggle.onclick = () => { if (open) hide(); else { open = true; layout(); close.focus(); } };
     20   close.onclick = backdrop.onclick = hide;
     21   mobile.addEventListener('change', layout);
     22   panel.addEventListener('keydown', event => {
     23     if (event.key === 'Escape') { event.preventDefault(); hide(); }
     24     if (event.key !== 'Tab' || !mobile.matches) return;
     25     const items = [...panel.querySelectorAll<HTMLElement>('button,input,select,textarea,a[href],summary,[tabindex="0"]')]
     26       .filter(e => !e.hasAttribute('disabled') && e.getClientRects().length > 0);
     27     const first = items[0], last = items.at(-1);
     28     if (event.shiftKey && document.activeElement === first) { event.preventDefault(); last?.focus(); }
     29     else if (!event.shiftKey && document.activeElement === last) { event.preventDefault(); first?.focus(); }
     30   });
     31   layout();
     32 }