Refactor Overlay to not use CSS

This commit is contained in:
Jordan Eldredge 2020-04-01 21:12:50 -07:00
parent 4cd0800cc0
commit 86f9abf5dd
3 changed files with 117 additions and 119 deletions

View file

@ -133,10 +133,6 @@ button:active {
margin-top: 46px; /* This matches the height of #search */
}
body.overlay-open {
overflow: hidden;
}
#webamp {
opacity: 0;
transition: opacity 400ms ease-in-out;
@ -163,32 +159,6 @@ body.webamp-loaded #webamp {
backface-visibility: hidden;
}
.overlay {
z-index: 1000;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0);
transition: background-color 400ms ease-out;
}
body.overlay-open .overlay {
background: rgba(0, 0, 0, 0.95);
}
#close-modal {
color: #a7a394;
position: fixed;
top: 10px;
right: 10px;
padding: 0;
font-size: 50px;
line-height: 25px;
text-decoration: none;
}
.metadata {
position: absolute;
margin: 10px;

View file

@ -1,97 +1,10 @@
import React from "react";
import ReactDOM from "react-dom";
import { connect } from "react-redux";
import * as ActionCreators from "./redux/actionCreators";
class Overlay extends React.Component {
constructor() {
super();
this._node = document.createElement("div");
this._node.classList.add("overlay");
this._handleKeyDown = this._handleKeyDown.bind(this);
this._handleClick = this._handleClick.bind(this);
this._handleTouchMove = this._handleTouchMove.bind(this);
window.document.body.appendChild(this._node);
}
componentDidMount() {
window.document.addEventListener("keydown", this._handleKeyDown);
window.document.addEventListener("touchmove", this._handleTouchMove);
// TODO: This is technically a race condition, since we could unmount before this fires.
if (this.props.shouldAnimate) {
setTimeout(() => {
// This does not seem to work the first time.
// This should _not_ work on page load
document.body.classList.add("overlay-open");
}, 0);
} else {
document.body.classList.add("overlay-open");
}
}
componentWillUnmount() {
window.document.body.removeChild(this._node);
window.document.removeEventListener("keydown", this._handleKeyDown);
window.document.removeEventListener("touchmove", this._handleTouchMove);
document.body.classList.remove("overlay-open");
}
_handleTouchMove(e) {
e.preventDefault();
}
_handleKeyDown(e) {
// Esc
if (e.keyCode === 27) {
this.props.closeModal();
}
}
_handleClick(e) {
if (e.target === e.currentTarget) {
this.props.closeModal();
}
}
render() {
return ReactDOM.createPortal(
<div
style={{
width: "100%",
height: "100%",
// This one werid hack to work around margin collapse which was making
// children with top margins cause the top protion of the overlay to
// be unclickable: https://stackoverflow.com/a/47351270/1263117
display: "flex",
flexDirection: "column"
}}
onClick={this._handleClick}
onScroll={e => e.stopPropagation()}
>
<a
id="close-modal"
href="/"
onClick={e => {
this.props.closeModal();
e.preventDefault();
}}
aria-label="Close Modal"
>
&times;
</a>
{this.props.children}
</div>,
this._node
);
}
}
import BaseOverlay from "./components/BaseOverlay";
const mapDispatchToProps = dispatch => ({
closeModal() {
dispatch(ActionCreators.closeModal());
}
});
export default connect(
null,
mapDispatchToProps
)(Overlay);
export default connect(null, mapDispatchToProps)(BaseOverlay);

View file

@ -0,0 +1,115 @@
import React, {
useEffect,
useCallback,
useLayoutEffect,
useState
} from "react";
import ReactDOM from "react-dom";
function handleTouchMove(e) {
e.preventDefault();
}
function Overlay({ shouldAnimate, closeModal, children }) {
const [mounted, setMounted] = useState();
useLayoutEffect(() => {
const timeout = setTimeout(() => {
setMounted(true);
});
const bodyOverflow = document.body.style.overflow;
document.body.style.overflow = "hidden";
return () => {
document.body.style.overflow = bodyOverflow;
if (timeout != null) {
clearTimeout(timeout);
}
};
}, []);
const handleClick = useCallback(
e => {
if (e.target === e.currentTarget) {
closeModal();
}
},
[closeModal]
);
const handleKeyDown = useCallback(
e => {
// Esc
if (e.keyCode === 27) {
closeModal();
}
},
[closeModal]
);
useEffect(() => {
window.document.addEventListener("keydown", handleKeyDown);
window.document.addEventListener("touchmove", handleTouchMove);
return () => {
window.document.removeEventListener("keydown", handleKeyDown);
window.document.removeEventListener("touchmove", handleTouchMove);
};
}, [handleKeyDown]);
return ReactDOM.createPortal(
<div
style={{
zIndex: 1000,
position: "fixed",
top: 0,
left: 0,
width: "100%",
height: "100%",
backgroundColor:
!shouldAnimate || mounted
? "rgba(0, 0, 0, 0.95)"
: "rgba(0, 0, 0, 0)",
transition: "background-color 400ms ease-out"
}}
>
<div
style={{
width: "100%",
height: "100%",
// This one werid hack to work around margin collapse which was making
// children with top margins cause the top protion of the overlay to
// be unclickable: https://stackoverflow.com/a/47351270/1263117
display: "flex",
flexDirection: "column"
}}
onClick={handleClick}
onScroll={handleTouchMove}
>
<a
id="close-modal"
href="/"
onClick={e => {
closeModal();
e.preventDefault();
}}
aria-label="Close Modal"
style={{
color: "#a7a394",
position: "fixed",
top: 10,
right: 10,
padding: 0,
fontSize: 50,
lineHeight: "25px",
textDecoration: "none"
}}
>
&times;
</a>
{children}
</div>
</div>,
window.document.body
);
}
export default Overlay;