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"));