본문 바로가기

Development

[UI 만들기] 2. Modal

 

 

  이번에 만들어 볼 UI는 Modal이다. Modal 역시 정말 많이 사용되는 UI이고 그 종류가 아주 많다. 그러나 이번에는 가장 간단한 Modal을 구현해보고자 한다. 이 바탕에 대부분의 Modal을 제작할 수 있다.

  Modal을 만들 때 React의 컴포넌트를 먼저 구성해야 하는데, 이 컴포넌트는 모달의 내용을 props로 전달받아야 한다. 이 컴포넌트는 기본적으로 렌더링을 담당하는 컴포넌트이다. 

import React from 'react';

type ModalProps = {
  content: JSX.Element;
  isOpen: boolean;
}

const Modal: React.FC<ModalProps> = ({ content, isOpen }) => {
  return (
    <>
      {isOpen && (
        <div className="overlay">
          <div className="modal">
            <div className="modal-content">{content}</div>
          </div>
        </div>
      )}
    </>
  )
}

Modal 컴포넌트는 오버레이 표시 여부를 제어하는 isOpen을 먼저 받는다. 그리고 isOpen이 true이면 컴포넌트가 오버레이가 그 안의 모달 컨텐츠를 렌더링한다. 스타일은 아래와 같다.

.overlay {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
}

.modal {
  background-color: #fff;
  padding: 20px;
  border-radius: 8px;
}

.modal-content {
  max-height: 80vh;
  overflow: auto;
}

overlay 클래스는 오버레이 스타일을 정의한다. 전체 뷰포트를 덮도록 고정된 요소를 배치하고 반투명 검은색 배경을 지정한다. modal 클래스는 모달 창의 스타일을 정의한다. 오버레이 내부의 요소를 중앙에 놓고 흰색 배경과 약간의 패딩을 제공했다. modal-content 클래스는 모달 내부 컨텐츠의 스타일을 정의한다. 컨텐츠의 높이를 뷰포트 80%로 제한하고 컨텐츠가 넘치면 스크롤 막대를 추가한다.

  이렇게 하고 Modal 컴포넌트를 사용하는 부모 컴포넌트에서 isOpen을 정의한다.

import React, { useState } from 'react';

const App:React.FC = () => {
  const [isModalOpen, setIsModalOpen] = useState(false);
  
  const handleModalToggle = () => {
    setIsModalOpen(!isModalOpen);
  };
  
  return (
    <div>
      <button onClick={handleModalToggle}>Open Modal</button>
      <Modal
        content={<p>This is the content of the modal window.</p>}
        isOpen={isModalOpen}
      />
    </div>
  )
}

 

 그런데 난 여기서 오버레이 화면을 클릭했을 때, 즉 모달 밖의 화면을 클릭했을 때 모달이 꺼지고 이전 화면으로 돌아가도록 구현하고 싶다.

type ModalProps = {
  content: JSX.Element;
  isOpen: boolean;
  onClose: () => void;
}

const Modal:React.FC<ModalProps> = ({ content, isOpen, onClose }) => {
  const handleOverlayClick = (e: React.MouseEvent<HTMLDivElement>) => {
    if (e.target === e.currentTarget) {
      onClose();
    }
  };
  
  return (
    <>
      {isOpen && (
        <div className="overlay" onClick={handleOverlayClick}>
          <div className="modal">
            <div className="modal-content">{content}</div>
          </div>
        </div>
      )}
    </>
  )
}

Modal 컴포넌트는 이제 모달을 닫아야 할 때 호출되는 함수인 onClose props를 받는다. handleOverlayClick 함수는 자식이 아닌 오버레이 자체가 클릭되었는지를 확인하는 onClick 핸들러이다. 오버레이를 클릭하면 onClose 함수가 호출되어 모달을 닫는다.

const App:React.FC = () => {
  const [isModalOpen, setIsModalOpen] = useState(false);
  
  cosnt handleModalToggle = () => {
    setIsModalOpen(!isModalOpen);
  };
  
  const handleCloseModal = () => {
    setIsModalOpen(false);
  }
  
  return (
    <div>
      <button onClick={handleModalToggle}>Open Modal</button>
      <Modal
        content={<p>This is the content of the modal window.</p>}
        isOpen={isModalOpen}
        onClose={handleCloseModal}
      />
    </div>
  )
}

handleCloseModal 함수는 단순히 isModalOpen 상태 변수를 false로 설정하여 모달을 닫는다. 이렇게 해서 오버레이를 클릭하면 Modal 컴포넌트가 닫히고 App 컴포넌트가 이 변경 사항을 반영하도록 업데이트한다.

'Development' 카테고리의 다른 글

[UI 만들기] 4. Popper  (0) 2023.04.05
[UI 만들기] 3. Top Navbar  (0) 2023.04.04
[UI 만들기] 1. Accordion  (0) 2023.03.24
chat GPT가 말하는 프론트엔드 개발자의 전망  (0) 2023.03.13