Created
December 21, 2016 22:57
-
-
Save chantastic/96fa78d1d48434b61fab1cec2cc0f4bb to your computer and use it in GitHub Desktop.
super-dumb-thing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Children, Component } from 'react'; | |
import ReactDOM from 'react-dom'; | |
class SetOverflowHidden extends Component { | |
componentDidMount() { | |
this.previousOverflow = document.body.style.overflow | |
document.body.style.overflow = "hidden" | |
} | |
componentWillUnmount() { | |
document.body.style.overflow = this.previousOverflow | |
} | |
render() { | |
return Children.only(this.props.children) | |
} | |
} | |
class ModalPortal extends Component { | |
// add way to interact with node | |
componentDidMount() { | |
this.node = document.createElement("div") | |
this.props.mountSelector().appendChild(this.node) | |
ReactDOM.render( | |
Children.only(this.props.children), | |
this.node | |
) | |
} | |
componentWillUnmount() { | |
ReactDOM.unmountComponentAtNode(this.node) | |
this.props.mountSelector().removeChild(this.node) | |
} | |
render() { | |
console.log(this.props.children) | |
return null | |
} | |
} | |
ModalPortal.defaultProps = { | |
mountSelector: () => document.body | |
} | |
ModalPortal.propTypes = { | |
children: React.PropTypes.node.isRequired | |
} | |
class OnEscapeClick extends Component { | |
handleKeyDown = () => { | |
if (event.keyCode == 27) { | |
event.preventDefault(); | |
return this.props.onEscapePress() | |
} | |
} | |
componentDidMount() { | |
document.addEventListener("keyup", this.handleKeyDown) | |
} | |
componentWillUnmount() { | |
document.removeEventListener("keyup", this.handleKeyDown) | |
} | |
render() { | |
return Children.only(this.props.children) | |
} | |
} | |
const ModalBackdrop = ({ style, ...props }) => | |
<div | |
style={{ | |
position: "fixed", | |
top: 0, | |
right: 0, | |
bottom: 0, | |
left: 0, | |
backgroundColor: "red", | |
overflowY: "scroll", | |
...style, | |
}} | |
{...props} | |
/> | |
class FetchData extends Component { | |
state = { data: null } | |
componentDidMount() { | |
this.setState({data: "blah blah blah"}) | |
} | |
render() { | |
return Children.only( | |
this.props.children(this.state) | |
) | |
} | |
} | |
class App extends Component { | |
state = { | |
modalShown: true | |
} | |
render() { | |
return ( | |
<div> | |
Sample App with composed Modal | |
<button | |
type="button" | |
onClick={() => this.setState({modalShown: true})} | |
>show modal</button> | |
{this.state.modalShown && | |
<FetchData> | |
{({ data }) => | |
<SetOverflowHidden> | |
<OnEscapeClick onEscapePress={() => this.setState({modalShown: false})}> | |
<ModalPortal> | |
<ModalBackdrop style={{ backgroundColor: "hsla(0, 0%, 0%, .25)"}}> | |
<div> | |
<div> | |
{data} | |
</div> | |
<footer> | |
<button | |
type="button" | |
onClick={() => this.setState({modalShown: !this.state.modalShown})} | |
>Cancel</button> | |
</footer> | |
</div> | |
</ModalBackdrop> | |
</ModalPortal> | |
</OnEscapeClick> | |
</SetOverflowHidden> | |
} | |
</FetchData> | |
} | |
</div> | |
); | |
} | |
} | |
export default App; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment