Skip to content

Instantly share code, notes, and snippets.

@mohandere
Last active October 12, 2017 15:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mohandere/b563d19f5f1c7bf027fd7129592e9ab8 to your computer and use it in GitHub Desktop.
Save mohandere/b563d19f5f1c7bf027fd7129592e9ab8 to your computer and use it in GitHub Desktop.
Higher Order Component for react-modal to handle modal bottom issue
import React from 'react';
import ReactModal from 'react-modal';
import withModal from './withModal';
class MyModal extends React.Component {
constructor(props) {
super(props)
this.state = {
showModal: this.props.show,
}
this.handleCloseModal = this.handleCloseModal.bind(this);
}
render() {
const style = {
content: {
bottom: this.props.bottom
}
}
return (
<ReactModal
isOpen={this.state.showModal}
contentLabel='welcome'
style={style}
portalClassName="my-modal"
onRequestClose={this.handleCloseModal}>
<div className="react-modal-dialog" ref="dialog">
<div className="react-modal-header">
<div className="title">{this.title}</div>
</div>
<div className="react-modal-body">
...
</div>
<div className="react-modal-footer">
<button className="btn close-modal-btn" onClick={this.handleCloseModal}>CLOSE</button>
</div>
</div>
</ReactModal>
)
}
}
export default withModal(MyModal)
import React from 'react';
import ReactDOM from 'react-dom';
function withModal(BaseModal) {
return class extends React.Component {
constructor(props) {
super(props);
this.state = {
contentHeight: 0
}
this.sizeDialog = this.sizeDialog.bind(this);
this.getModalBottom = this.getModalBottom.bind(this);
}
componentDidUpdate() {
if (window.requestAnimationFrame) {
window.requestAnimationFrame(this.sizeDialog);
} else {
window.setTimeout(this.sizeDialog, 50);
}
}
sizeDialog() {
let contentEl = this.child.refs.dialog
if (!contentEl) {
return;
}
let contentHeight = contentEl.getBoundingClientRect().height;
if (contentHeight !== this.state.contentHeight) {
this.setState({
contentHeight
});
}
}
getModalBottom() {
let {
contentHeight
} = this.state
if (!contentHeight) {
return '40px'; // Default
}
let clientHeight = Math.max(document.documentElement.clientHeight,
window.innerHeight || 0
);
// 80 is top + bottom for `ReactModal__Content` in pixels
// 40 is padding applied for `ReactModal__Content` in pixels
let offsetInPx = 80 + 40
let isContentHeightMore = (contentHeight + offsetInPx) > clientHeight
// if `clientHeight` is more than `contentHeight` and additional `offset`
// Means
let modalBottom = isContentHeightMore ? '40px' : 'auto'
// console.log('Log @isContentHeightMore =', isContentHeightMore)
return modalBottom
}
render() {
return <BaseModal
bottom={this.getModalBottom()}
{...this.props}
ref={(node) => { this.child = node; }} />;
}
}
}
export default withModal
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment