1
0
mirror of https://github.com/chinchang/web-maker.git synced 2025-07-28 17:20:13 +02:00
Files
php-web-maker/src/components/Modal.jsx
2018-07-05 11:05:39 +05:30

82 lines
2.1 KiB
JavaScript

import { h, Component } from 'preact';
import Portal from 'preact-portal';
export default class Modal extends Component {
componentDidMount() {
window.addEventListener('keydown', this.onKeyDownHandler.bind(this));
}
componentWillUnmount() {
window.removeEventListener('keydown', this.onKeyDownHandler.bind(this));
if (this.focusGrabber) {
this.focusGrabber.remove();
this.focusGrabber = null;
}
}
onKeyDownHandler(e) {
if (e.keyCode === 27) {
this.props.closeHandler();
}
}
onOverlayClick(e) {
if (e.target === this.overlayEl) {
this.props.closeHandler();
}
}
componentDidUpdate(prevProps) {
if (this.props.show !== prevProps.show) {
document.body.classList[this.props.show ? 'add' : 'remove'](
'overlay-visible'
);
if (this.props.show) {
// HACK: refs will evaluate on next tick due to portals
setTimeout(() => {
this.overlayEl.querySelector('.js-modal__close-btn').focus();
}, 0);
/* We insert a dummy hidden input which will take focus as soon as focus
escapes the modal, instead of focus going outside modal because modal
is last focusable element. */
this.focusGrabber = document.createElement('input');
this.focusGrabber.setAttribute(
'style',
'height:0;opacity:0;overflow:hidden;width:0;'
);
setTimeout(() => {
document.body.appendChild(this.focusGrabber);
}, 10);
} else {
this.focusGrabber.remove();
this.focusGrabber = null;
}
}
}
render() {
if (!this.props.show) return null;
return (
<Portal into="body">
<div
class={`${this.props.extraClasses || ''} modal is-modal-visible ${
this.props.small ? 'modal--small' : ''
}`}
ref={el => (this.overlayEl = el)}
onClick={this.onOverlayClick.bind(this)}
>
<div class="modal__content">
<button
type="button"
onClick={this.props.closeHandler}
aria-label="Close modal"
title="Close"
class="js-modal__close-btn modal__close-btn"
>
Close
</button>
{this.props.children}
</div>
</div>
</Portal>
);
}
}