UNPKG

@massds/mayflower-react

Version:

React versions of Mayflower design system UI components

58 lines (55 loc) 2.8 kB
/** * focusTrapping: Trap keyboard focus inside of a modal * @param {string} focusableSelectors(requied): css selectors for all the focusable elements inside of the modal * @param {string} modalSelector(requied): css selector for the modal container * @param {string} closeButtonSelector(optional): If the modal close button is outside of the modal container, add the css selector for it to be included as the first focusable element * @param {event} key(requied): keydown event */ // check if an element is visibly displayed using computed style const isDisplayed = el => { const style = window.getComputedStyle(el); return style.display !== 'none' && style.visibility !== 'hidden'; }; // filter out elements from array which are not visibly displayed const filterDisplayedElements = elements => elements.length > 0 && elements.filter(el => isDisplayed(el)); export default _ref => { let _ref$focusableSelecto = _ref.focusableSelectors, focusableSelectors = _ref$focusableSelecto === void 0 ? 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' : _ref$focusableSelecto, closeButtonSelector = _ref.closeButtonSelector, modalSelector = _ref.modalSelector, keyEvent = _ref.keyEvent; // add all the elements inside modal which you want to make focusable const focusableElements = focusableSelectors; const modal = document.querySelector(modalSelector); // select the modal by its id const key = keyEvent.key; const action = { tab: key === 'Tab', // tab shift: key.shift // shift }; if (modal) { const focusableNodeArray = Array.from(modal.querySelectorAll(focusableElements)); let focusableContent = modal && filterDisplayedElements(focusableNodeArray); if (closeButtonSelector) { const closeButton = document.querySelector(closeButtonSelector); focusableContent = [closeButton].concat(focusableContent); } const focusedElement = document.activeElement; const firstFocusableElement = focusableContent[0]; // get first element to be focused inside modal const lastFocusableElement = focusableContent[focusableContent.length - 1]; // get last element to be focused inside modal const isTabPressed = action.tab; if (!isTabPressed) { return; } if (action.shift) { // if shift key pressed for shift + tab combination if (focusedElement === firstFocusableElement) { lastFocusableElement.focus(); // add focus for the last focusable element } } else if (focusedElement === lastFocusableElement) { // if tab key is pressed // if focused has reached to last focusable element then focus first focusable element after pressing tab firstFocusableElement.focus(); // add focus for the first focusable element } } };