Skip to content

Commit

Permalink
fix(drawer): replace focus trap with vanilla version (#437)
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt Goo committed Nov 20, 2018
1 parent 8e28944 commit bd7433b
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 36 deletions.
27 changes: 10 additions & 17 deletions packages/drawer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,20 @@
import React from 'react';
import classnames from 'classnames';
import PropTypes from 'prop-types';
import {MDCDismissibleDrawerFoundation, MDCModalDrawerFoundation} from '@material/drawer';
import {MDCDismissibleDrawerFoundation, MDCModalDrawerFoundation, util} from '@material/drawer';
import {MDCListFoundation} from '@material/list';
import DrawerHeader from './Header';
import DrawerContent from './Content';
import DrawerSubtitle from './Subtitle';
import DrawerTitle from './Title';
import DrawerAppContent from './AppContent';
import FocusTrap from 'focus-trap-react';

const {cssClasses: listCssClasses} = MDCListFoundation;

class Drawer extends React.Component {
previousFocus_ = null;
foundation_ = null;
focusTrap_ = null;
drawerElement_ = React.createRef();

state = {classList: new Set()};
Expand All @@ -47,6 +47,7 @@ class Drawer extends React.Component {
this.foundation_ = new MDCDismissibleDrawerFoundation(this.adapter);
this.foundation_.init();
} else if (modal) {
this.initializeFocusTrap();
this.foundation_ = new MDCModalDrawerFoundation(this.adapter);
this.foundation_.init();
}
Expand All @@ -70,6 +71,10 @@ class Drawer extends React.Component {
this.foundation_.destroy();
}

initializeFocusTrap = () => {
this.focusTrap_ = util.createFocusTrapInstance(this.drawerElement_.current);
}

get classes() {
const {classList} = this.state;
const {className, dismissible, modal} = this.props;
Expand Down Expand Up @@ -116,8 +121,8 @@ class Drawer extends React.Component {
},
notifyClose: this.props.onClose,
notifyOpen: this.props.onOpen,
trapFocus: () => this.setState({activeFocusTrap: true}),
releaseFocus: () => this.setState({activeFocusTrap: false}),
trapFocus: () => this.focusTrap_ && this.focusTrap_.activate(),
releaseFocus: () => this.focusTrap_ && this.focusTrap_.deactivate(),
};
}

Expand All @@ -134,7 +139,6 @@ class Drawer extends React.Component {
}

render() {
const {activeFocusTrap} = this.state;
const {
/* eslint-disable no-unused-vars */
onClose,
Expand All @@ -150,13 +154,6 @@ class Drawer extends React.Component {
...otherProps
} = this.props;

const focusTrapOptions = {
clickOutsideDeactivates: true,
initialFocus: false,
escapeDeactivates: false,
returnFocusOnDeactivate: false,
};

return (
<React.Fragment>
<Tag
Expand All @@ -165,11 +162,7 @@ class Drawer extends React.Component {
onTransitionEnd={(evt) => this.handleTransitionEnd(evt)}
{...otherProps}
>
{activeFocusTrap ? (
<FocusTrap focusTrapOptions={focusTrapOptions}>
{children}
</FocusTrap>
): children}
{children}
</Tag>
{modal ? this.renderScrim() : null}
</React.Fragment>
Expand Down
2 changes: 1 addition & 1 deletion packages/drawer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"@material/drawer": "^0.41.0",
"@material/list": "^0.41.0",
"classnames": "^2.2.5",
"focus-trap-react": "^4.0.1",
"focus-trap": "^3.0.0",
"prop-types": "^15.6.1",
"react": "^16.4.2"
},
Expand Down
26 changes: 8 additions & 18 deletions test/unit/drawer/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,17 +156,20 @@ test('#adapter.notifyOpen calls props.onOpen', () => {
td.verify(onOpen(), {times: 1});
});

test('#adapter.trapFocus sets state.activeFocusTrap to true', () => {
test('#adapter.trapFocus calls focusTrap.activate if modal variant', () => {
const wrapper = shallow(<Drawer modal />);
const activate = td.func();
wrapper.instance().focusTrap_ = {activate};
wrapper.instance().foundation_.adapter_.trapFocus();
assert.isTrue(wrapper.state().activeFocusTrap);
td.verify(activate(), {times: 1});
});

test('#adapter.releaseFocus sets state.activeFocusTrap to false', () => {
test('#adapter.releaseFocus calls focusTrap.deactivate if modal variant', () => {
const wrapper = shallow(<Drawer modal />);
wrapper.setState({activeFocusTrap: false});
const deactivate = td.func();
wrapper.instance().focusTrap_ = {deactivate};
wrapper.instance().foundation_.adapter_.releaseFocus();
assert.isFalse(wrapper.state().activeFocusTrap);
td.verify(deactivate(), {times: 1});
});

test('event keydown triggers props.onKeyDown', () => {
Expand Down Expand Up @@ -201,19 +204,6 @@ test('event transitionend triggers foundation.handleTransitionEnd', () => {
td.verify(wrapper.instance().foundation_.handleTransitionEnd(evt), {times: 1});
});

test('renders child when state.activeFocusTrap is false', () => {
const wrapper = shallow(<Drawer><span>meow</span></Drawer>);
const text = wrapper.childAt(0).childAt(0).text();
assert.equal(text, 'meow');
});

test('renders FocusTrap with children when state.activeFocusTrap is true', () => {
const wrapper = shallow(<Drawer><span>meow</span></Drawer>);
wrapper.setState({activeFocusTrap: true});
assert.equal(wrapper.childAt(0).childAt(0).name(), 'FocusTrap');
assert.equal(wrapper.childAt(0).childAt(0).childAt(0).text(), 'meow');
});

test('does not render scrim when props.modal is false', () => {
const wrapper = shallow(<Drawer />);
assert.equal(wrapper.childAt(1).type(), null);
Expand Down

0 comments on commit bd7433b

Please sign in to comment.