diff options
author | Starfall <root@starfall.blue> | 2019-12-09 19:07:33 -0600 |
---|---|---|
committer | Starfall <root@starfall.blue> | 2019-12-09 19:09:31 -0600 |
commit | 6b34fcfef7566105e8d80ab5fee0a539c06cddbf (patch) | |
tree | 8fad2d47bf8be255d3c671c40cbfd04c2f55ed03 /app/javascript/flavours/glitch/components/modal_root.js | |
parent | 9fbb4af7611aa7836e65ef9f544d341423c15685 (diff) | |
parent | 246addd5b33a172600342af3fb6fb5e4c80ad95e (diff) |
Merge branch 'glitch'`
Diffstat (limited to 'app/javascript/flavours/glitch/components/modal_root.js')
-rw-r--r-- | app/javascript/flavours/glitch/components/modal_root.js | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/app/javascript/flavours/glitch/components/modal_root.js b/app/javascript/flavours/glitch/components/modal_root.js index 4e8648b49..f9877d5ea 100644 --- a/app/javascript/flavours/glitch/components/modal_root.js +++ b/app/javascript/flavours/glitch/components/modal_root.js @@ -1,5 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; +import 'wicg-inert'; import createHistory from 'history/createBrowserHistory'; export default class ModalRoot extends React.PureComponent { @@ -26,8 +27,30 @@ export default class ModalRoot extends React.PureComponent { } } + handleKeyDown = (e) => { + if (e.key === 'Tab') { + const focusable = Array.from(this.node.querySelectorAll('button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])')).filter((x) => window.getComputedStyle(x).display !== 'none'); + const index = focusable.indexOf(e.target); + + let element; + + if (e.shiftKey) { + element = focusable[index - 1] || focusable[focusable.length - 1]; + } else { + element = focusable[index + 1] || focusable[0]; + } + + if (element) { + element.focus(); + e.stopPropagation(); + e.preventDefault(); + } + } + } + componentDidMount () { window.addEventListener('keyup', this.handleKeyUp, false); + window.addEventListener('keydown', this.handleKeyDown, false); this.history = this.context.router ? this.context.router.history : createHistory(); } @@ -39,15 +62,22 @@ export default class ModalRoot extends React.PureComponent { } else if (!nextProps.children) { this.setState({ revealed: false }); } - if (!nextProps.children && !!this.props.children) { - this.activeElement.focus({ preventScroll: true }); - this.activeElement = null; - } } componentDidUpdate (prevProps) { if (!this.props.children && !!prevProps.children) { this.getSiblings().forEach(sibling => sibling.removeAttribute('inert')); + + // Because of the wicg-inert polyfill, the activeElement may not be + // immediately selectable, we have to wait for observers to run, as + // described in https://github.com/WICG/inert#performance-and-gotchas + Promise.resolve().then(() => { + this.activeElement.focus({ preventScroll: true }); + this.activeElement = null; + }).catch((error) => { + console.error(error); + }); + this.handleModalClose(); } if (this.props.children) { @@ -60,6 +90,7 @@ export default class ModalRoot extends React.PureComponent { componentWillUnmount () { window.removeEventListener('keyup', this.handleKeyUp); + window.removeEventListener('keydown', this.handleKeyDown); } handleModalClose () { |