Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable focus trap & disable tab trap #876

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/index.md
Expand Up @@ -100,6 +100,22 @@ import ReactModal from 'react-modal';
true
/* Boolean indicating if the modal should be focused after render. */}

disableFocusTrap={
false
/*
Boolean indicating if the modal should allow focus to leave the modal when it's visible.
If you set this flag to true, it's likely that you'll want to set disableTabTrap=true also,
to allow focus to leave the modal using the tab button.
*/}

disableTabTrap={
true
/*
Boolean indicating if the modal should allow focus to leave the modal using the tab key.
If you set this flag to true, it's likely that you'll want to set disableFocusTrap=true also,
because otherwise the focus will be prevented from leaving the component.
*/}

shouldCloseOnOverlayClick={
true
/* Boolean indicating if the overlay should close the modal */}
Expand Down
19 changes: 19 additions & 0 deletions specs/Modal.events.spec.js
Expand Up @@ -109,6 +109,25 @@ export default () => {
});
});


it("does NOT keep focus inside the modal when child has no tabbable elements and disableTabTrap === true", () => {
let tabPrevented = false;
const props = {
isOpen: true,
disableTabTrap: true,
};
withModal(props, "hello", modal => {
const content = mcontent(modal);
document.activeElement.should.be.eql(content);
tabKeyDown(content, {
preventDefault() {
tabPrevented = true;
}
});
tabPrevented.should.be.eql(false);
});
});

describe("shouldCloseOnEsc", () => {
context("when true", () => {
it("should close on Esc key event", () => {
Expand Down
4 changes: 3 additions & 1 deletion src/components/ModalPortal.js
Expand Up @@ -59,6 +59,8 @@ export default class ModalPortal extends Component {
shouldFocusAfterRender: PropTypes.bool,
shouldCloseOnOverlayClick: PropTypes.bool,
shouldReturnFocusAfterClose: PropTypes.bool,
disableFocusTrap: PropTypes.bool,
disableTabTrap: PropTypes.bool,
preventScroll: PropTypes.bool,
role: PropTypes.string,
contentLabel: PropTypes.string,
Expand Down Expand Up @@ -273,7 +275,7 @@ export default class ModalPortal extends Component {
};

handleKeyDown = event => {
if (event.keyCode === TAB_KEY) {
if (event.keyCode === TAB_KEY && !this.props.disableTabTrap) {
bvellacott marked this conversation as resolved.
Show resolved Hide resolved
scopeTab(this.content, event);
}

Expand Down
4 changes: 3 additions & 1 deletion src/helpers/bodyTrap.js
Expand Up @@ -53,7 +53,9 @@ function bodyTrap(eventType, openInstances) {

instances = openInstances;

if (instances.length > 0) {
const trapFocus = instances.find(({ props }) => !props.disableFocusTrap);

if (trapFocus && instances.length > 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if we open one modal with focus trap disabled and one that's enabled?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then a focus trap will exist. I thought that is the best way to do it as it gives existing functionality priority over the added functionality. I could add something in the readme to let the user know?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a comment in the readme about this

// Add focus trap
if (document.body.firstChild !== before) {
document.body.insertBefore(before, document.body.firstChild);
Expand Down