From 2e90fa9ae1373ca1ee4a4f585c94c8af5f9cd564 Mon Sep 17 00:00:00 2001 From: Kushagra Gour Date: Fri, 22 Jun 2018 14:21:29 +0530 Subject: [PATCH] port focus trapping in modal --- src/components/Modal.jsx | 19 +++++++++++++++++++ src/components/app.jsx | 14 ++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/components/Modal.jsx b/src/components/Modal.jsx index 10d3494..b4e93d4 100644 --- a/src/components/Modal.jsx +++ b/src/components/Modal.jsx @@ -7,6 +7,10 @@ export default class Modal extends Component { } componentWillUnmount() { window.removeEventListener('keydown', this.onKeyDownHandler.bind(this)); + if (this.focusGrabber) { + this.focusGrabber.remove(); + this.focusGrabber = null; + } } onKeyDownHandler(e) { if (e.keyCode === 27) { @@ -28,6 +32,21 @@ export default class Modal extends Component { setTimeout(() => { this.overlayEl.querySelector('.js-modal__close-btn').focus(); }, 0); + + /* We insert a dummy hidden input which will take focus as soon as focus + escapes the modal, instead of focus going outside modal because modal + is last focusable element. */ + this.focusGrabber = document.createElement('input'); + this.focusGrabber.setAttribute( + 'style', + 'height:0;opacity:0;overflow:hidden;width:0;' + ); + setTimeout(() => { + document.body.appendChild(this.focusGrabber); + }, 10); + } else { + this.focusGrabber.remove(); + this.focusGrabber = null; } } } diff --git a/src/components/app.jsx b/src/components/app.jsx index 6e0e919..821bedd 100644 --- a/src/components/app.jsx +++ b/src/components/app.jsx @@ -463,6 +463,20 @@ export default class App extends Component { this.closeSavedItemsPane(); } }); + + // Basic Focus trapping + window.addEventListener('focusin', e => { + if (document.body.classList.contains('overlay-visible')) { + const modal = $('.is-modal-visible'); + if (!modal) { + return; + } + if (!modal.contains(e.target)) { + e.preventDefault(); + modal.querySelector('.js-modal__close-btn').focus(); + } + } + }); } closeAllOverlays() {