React
by Aaron Balthaser
HTML
<div id="app"></div>
SCSS
.modal-overlay {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.45);
}
.modal {
display: flex;
overflow: hidden;
flex-direction: column;
background: #fff;
border-radius: 20px;
&-enter {
transform: translateY(100vh);
}
&-enter-active {
transform: translateY(0);
transition: 350ms ease-out;
}
&-exit {
transform: translateY(0);
}
&-exit-active {
transform: translateY(100vh);
transition: 350ms ease-out;
}
&__header {
position: absolute;
z-index: 2;
align-self: flex-end;
}
&__close-btn {
width: 40px;
height: 40px;
padding: 0;
margin-top: 30px;
border: none;
background: none;
border-radius: 50%;
color: #6c6c70;
cursor: pointer;
font-size: 33px;
font-weight: 600;
margin-inline-end: 30px;
&::before {
content: '\f314';
}
&:active {
color: rgba(108, 108, 112, 0.7);
}
}
}
React
const ModalHeader = ({ onClose }) => {
return (
<div className="modal__header">
<button
className="modal__close-btn"
data-testid="modal-close-button"
onClick={onClose}
/>
</div>
);
};
const Modal = ({children}) => {
const [state, setState] = React.useState(true);
const handleCloseOutsideClick = () => {
setState(false);
};
const handleCloseButtonClick = () => {
setState(false);
};
const renderModal = () => {
return (
<div
className="modal-overlay"
onClick={handleCloseOutsideClick}
>
<div className="modal">
<ModalHeader onClose={handleCloseButtonClick} />
{children}
</div>
</div>
);
};
return state ? renderModal() : null;
};
const App = () => {
return (
<Modal>
<div>Modal Children</div>
</Modal>
);
};
ReactDOM.render(<App />, document.querySelector("#app"));