Skip to content

Commit

Permalink
Add customOnKeyDown prop
Browse files Browse the repository at this point in the history
  • Loading branch information
negomi committed Mar 30, 2018
1 parent a206da8 commit 55ded85
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 5 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,26 @@ By default, the menu will close when the Escape key is pressed. To disable this
<Menu disableCloseOnEsc />
```

#### Custom `window.onkeydown` handler

For more control over global keypress functionality, you can override the handler that this component sets for `window.onkeydown`, and pass a custom function. This could be useful if you are using multiple instances of this component, for example, and want to implement functionality to ensure that a single press of the Escape key closes them all.

``` javascript
const closeAllMenusOnEsc = (e) => {
e = e || window.event;

if (e.key === 'Escape' || e.keyCode === 27) {
this.setState({areMenusOpen: false});
}
};

// Because we can only set one window.onkeydown handler, the last menu you include will override any handlers set by previous ones.
// For that reason, it's recommended that you pass the same function to all menus to avoid unexpected behavior.
<MenuOne customOnKeyDown={closeAllMenusOnEsc} isOpen={areMenusOpen} />
<MenuTwo customOnKeyDown={closeAllMenusOnEsc} isOpen={areMenusOpen} />
```
*Note: Using this prop will disable all the default 'close on Escape' functionality, so you will need to handle this (including determining which key was pressed) yourself.*

#### Overlay

You can turn off the default overlay with `noOverlay`.
Expand Down
7 changes: 5 additions & 2 deletions lib/menuFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,10 @@ exports['default'] = function (styles) {
}, {
key: 'componentDidMount',
value: function componentDidMount() {
// Bind ESC key handler (unless disabled)
if (!this.props.disableCloseOnEsc) {
// Bind ESC key handler (unless disabled or custom function supplied).
if (this.props.customOnKeyDown) {
window.onkeydown = this.props.customOnKeyDown;
} else if (!this.props.disableCloseOnEsc) {
window.onkeydown = this.listenForClose.bind(this);
}

Expand Down Expand Up @@ -344,6 +346,7 @@ exports['default'] = function (styles) {
crossClassName: _propTypes2['default'].string,
customBurgerIcon: _propTypes2['default'].oneOfType([_propTypes2['default'].element, _propTypes2['default'].oneOf([false])]),
customCrossIcon: _propTypes2['default'].oneOfType([_propTypes2['default'].element, _propTypes2['default'].oneOf([false])]),
customOnKeyDown: _propTypes2['default'].func,
disableCloseOnEsc: _propTypes2['default'].bool,
disableOverlayClick: _propTypes2['default'].oneOfType([_propTypes2['default'].bool, _propTypes2['default'].func]),
id: _propTypes2['default'].string,
Expand Down
7 changes: 5 additions & 2 deletions src/menuFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,10 @@ export default styles => {
}

componentDidMount() {
// Bind ESC key handler (unless disabled)
if (!this.props.disableCloseOnEsc) {
// Bind ESC key handler (unless disabled or custom function supplied).
if (this.props.customOnKeyDown) {
window.onkeydown = this.props.customOnKeyDown;
} else if (!this.props.disableCloseOnEsc) {
window.onkeydown = this.listenForClose.bind(this);
}

Expand Down Expand Up @@ -291,6 +293,7 @@ export default styles => {
PropTypes.element,
PropTypes.oneOf([false])
]),
customOnKeyDown: PropTypes.func,
disableCloseOnEsc: PropTypes.bool,
disableOverlayClick: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
id: PropTypes.string,
Expand Down
16 changes: 15 additions & 1 deletion test/menuFactory.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ describe('menuFactory', () => {
});
});

describe('disableCloseOnEsc', () => {
describe('disableCloseOnEsc prop', () => {

it('should not allow close on Escape key press', () => {
Menu = menuFactory(mockStyles.basic);
Expand All @@ -518,6 +518,20 @@ describe('menuFactory', () => {
});
});

describe('customOnKeyDown prop', () => {

it('should be set for window.onkeydown instead of listenForClose', () => {
Menu = menuFactory(mockStyles.basic);
const customOnKeyDown = sinon.spy();
component = TestUtils.renderIntoDocument(<Menu customOnKeyDown={customOnKeyDown} />);
const listenForClose = sinon.spy(component, 'listenForClose');
component.setState({ isOpen: true });
window.onkeydown();
expect(customOnKeyDown.called).to.be.true;
expect(listenForClose.called).to.be.false;
});
});

describe('open state', () => {

let container;
Expand Down

0 comments on commit 55ded85

Please sign in to comment.