React - 在Tab键时防止焦点退出模态

时间:2017-07-04 09:08:13

标签: javascript css reactjs modal-dialog

我已经建立了自己的反应模式。当我打开模态时按Tab键,焦点仍然会转到背景页面。如何限制模态内组件的焦点?

下面的逻辑应该是什么?

onKeyPress (e) {
   if (e.keyCode === 9) {
       e.preventDefault();
      // logic here?
   }
}

反应模态代码:

<ReactModal onKeyPress={this.onKeyPress} >
   <input type="text"/>
   <input type="text"/>
</ReactModal>

2 个答案:

答案 0 :(得分:3)

嗯,你可以使用聚焦陷阱来做到这一点。请查看此npm module。只需将包含模态的内容包裹在这样的焦点陷阱中。

    <FocusTrap
              focusTrapOptions={{
                ...
              }}
            >
              <div className="trap">
                <p>
                  Here is a focus trap
                  {' '}
                  <a href="#">with</a>
                  {' '}
                  <a href="#">some</a>
                  {' '}
                  <a href="#">focusable</a>
                  {' '}
                  parts.
                </p>
                <p>
                  <button onClick={this.someCallback}>
                    Click Me
                  </button>
                </p>
              </div>

</FocusTrap>

我建议你不要自己实现它,而不是给你实现这个的建议。考虑到可访问性很难做到正确。

相反,我建议您使用可访问的现成模态组件,例如react-modal。它是完全可定制的,您可以在其中放置任何您想要的内容,但它可以正确处理可访问性,以便盲人仍然可以使用您的模态。

答案 1 :(得分:0)

我必须将焦点锁定在我们在React组件中使用的模式中。我添加了用于DOWN的eventListner并收集了Tab和Shift + Tab

class Modal extends Component {
    componentDidMount() {
        window.addEventListener("keyup", this.handleKeyUp, false);
        window.addEventListener("keydown", this.handleKeyDown, false);
    }

    componentWillUnmount() {
        window.removeEventListener("keyup", this.handleKeyUp, false);
        window.removeEventListener("keydown", this.handleKeyDown, false);
    }

    handleKeyDown = (e) => {

        //Fetch node list from which required elements could be grabbed as needed.
        const modal = document.getElementById("modal_parent");
        const tags = [...modal.querySelectorAll('select, input, textarea, button, a, li')].filter(e1 => window.getComputedStyle(e1).getPropertyValue('display') === 'block');
        const focusable = modal.querySelectorAll('button, [href], input, select, textarea, li, a,[tabindex]:not([tabindex="-1"])');
        const firstFocusable = focusable[0];
        const lastFocusable = focusable[focusable.length - 1];

        if (e.ctrlKey || e.altKey) {
            return;
        }

        const keys = {
            9: () => { //9 = TAB
                if (e.shiftKey && e.target === firstFocusable) {
                    lastFocusable.focus();
                }

                if (e.target === lastFocusable) {
                    firstFocusable.focus();
                }
            }
        };

        if (keys[e.keyCode]) {
            keys[e.keyCode]();
        }
    }
}