UNPKG

terra-abstract-modal

Version:

The abstract modal is a structural component that provides the ability to display portal'd content in a layer above the app.

66 lines (57 loc) 3 kB
/** * This helper updates the root dom element to update the overlay count used to manage multiple layers * of inert requesting components. If the inert count is zero, it adds the inert attribute to the root dom * element. Additionally, it shifts the focus to the disclosing content for screen readers and keyboard navigation. * * @param {HTMLElement} modalElement - the reference to the modal that is being opened. * @param {string} rootSelector - the root-level attribute to apply inert to. */ function showModalDomUpdates(modalElement, rootSelector) { const mainDocumentElement = document.querySelector(rootSelector); if (mainDocumentElement) { const dataOverlayCount = +mainDocumentElement.getAttribute('data-abstract-modal-overlay-count'); if (dataOverlayCount < 1) { mainDocumentElement.setAttribute('inert', 'true'); } mainDocumentElement.setAttribute('data-abstract-modal-overlay-count', `${dataOverlayCount + 1}`); if (modalElement.querySelector('[data-terra-abstract-modal-begin]')) { modalElement.querySelector('[data-terra-abstract-modal-begin]').focus(); } else { // Shift focus to modal dialog modalElement.focus(); } } } /** * This helper updates the root dom element to reduce a overlay count used to manage multiple layers of inert * requesting components. If the inert count is one, it removes inert from the root dom element. Additionally, it * shifts the focus back to the previously focused element for screen readers and keyboard navigation. * * @param {HTMLElement} modalTriggerElement - reference to the element that requested that the abstract modal open. * @param {string} rootSelector - the root-level attribute to remove inert from. */ function hideModalDomUpdates(modalTriggerElement, rootSelector) { const mainDocumentElement = document.querySelector(rootSelector); if (mainDocumentElement) { const dataOverlayCount = +mainDocumentElement.getAttribute('data-abstract-modal-overlay-count'); if (dataOverlayCount === 1) { mainDocumentElement.removeAttribute('data-abstract-modal-overlay-count'); mainDocumentElement.removeAttribute('inert'); } else if (dataOverlayCount > 1) { mainDocumentElement.setAttribute('data-abstract-modal-overlay-count', `${dataOverlayCount - 1}`); } } // Allows inert processing to finish or focus will not shift back setTimeout(() => { if (modalTriggerElement && modalTriggerElement.focus) { // Shift focus back to element that was last focused prior to opening the modal modalTriggerElement.focus(); } else { // In some cases on IE, when the focus cannot be restored on the element (SVG element, for instance) // that was last focused prior to opening the modal, place the focus on the HTML body element to repro // the behavior noticed on other major browsers. document.querySelector('body').focus(); } }, 0); } export { showModalDomUpdates, hideModalDomUpdates };