Skip to content

Commit

Permalink
tc - allow content within modals to autofocus
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim Connor committed Apr 27, 2017
1 parent 2446a97 commit 2b7b33b
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 3 deletions.
25 changes: 24 additions & 1 deletion src/components/Modal.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,27 @@
import { Modal } from 'reactstrap';
import { Modal as ReactstrapModal } from 'reactstrap';

/**
* TODO
* As of 04/27/2017 the reactstrap Modal class will autofocus itself upon opening, preventing any
* elements within the modal from autofocusing.
*
* There is a PR open with a fix here https://github.com/reactstrap/reactstrap/pull/389 that solves
* the problem by allowing users to pass autofocus={false} to Modals. When the PR has been merged
* we can remove the togglePortal override below.
*/
class Modal extends ReactstrapModal {
togglePortal() {
if (this.props.isOpen) {
// See https://github.com/reactstrap/reactstrap/pull/389/files#diff-3ddc036af206541151e86f03cfc0c0eeR113
if (this.props.autoFocus !== false) {
this._focus = true;
}
this.show();
} else {
this.hide();
}
}
}

Modal.defaultProps = {
...Modal.defaultProps,
Expand Down
80 changes: 78 additions & 2 deletions test/components/Modal.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,88 @@ import 'jsdom-global/register';
import React from 'react';
import assert from 'assert';
import { mount } from 'enzyme';
import { Button } from 'reactstrap';

import { Modal } from '../../src';

describe('<Modal />', () => {
const component = mount(<Modal />);
const noop = () => {};

describe.only('<Modal />', () => {
let component;

afterEach(done => {
if (component && component.prop('isOpen')) {
component.setProps({ isOpen: false });
const interval = setInterval(() => {
if (!document.getElementsByClassName('modal').length) {
clearInterval(interval);
component = null;
done();
}
}, 100);
} else {
done();
}
});

it('should render correctly', () => {
component = mount(<Modal toggle={noop} />);
assert(component);
});

context('when autoFocus="true"', () => {
it('sets focus to the modal content', () => {
const originalActiveElement = document.activeElement;
component = mount(
<Modal isOpen={false} toggle={noop}>
<Button id="button">This button</Button> should not have focus
</Modal>
);

// After mounting the active element should not have changed
assert.equal(document.activeElement, originalActiveElement);

component.setProps({ isOpen: true });

// Now the modal is open the original focused element should still maintain focus
const content = document.getElementsByClassName('modal')[0];
assert.equal(document.activeElement, content);
});
});

context('when autoFocus="false"', () => {
it('leaves focus as-is if elements within the modal are not autofocus', () => {
const originalActiveElement = document.activeElement;
component = mount(
<Modal isOpen={false} autoFocus={false} toggle={noop}>
<Button id="button">This button</Button> should not have focus
</Modal>
);

// After mounting the active element should not have changed
assert.equal(document.activeElement, originalActiveElement);

component.setProps({ isOpen: true });

// Now the modal is open the original focused element should still maintain focus
assert.equal(document.activeElement, originalActiveElement);
});

it('allows elements within the modal to have focus', () => {
const originalActiveElement = document.activeElement;
component = mount(
<Modal isOpen={false} autoFocus={false} toggle={noop}>
<Button id="button" autoFocus>This button</Button> should have focus
</Modal>
);

// After mounting the active element should not have changed
assert.equal(document.activeElement, originalActiveElement);

component.setProps({ isOpen: true });

// Now the modal is open the button should have focus
assert.equal('button', document.activeElement.id);
});
});
});

0 comments on commit 2b7b33b

Please sign in to comment.