Today I Learn/React

[React] 라이브러리 없이 모달 구현하기(TailWind Css, 애니메이션 효과, 배경 스크롤 막기)

단추언니 2024. 11. 26. 13:09
반응형

포트폴리오 사이트를 react로 구현하던 중 모달 기능이 필요하여 라이브러리를 사용하지 않고 만들었다.

// Modal.jsx
import React from 'react';

export default function Modal({ open, close, title, children }) {
  if (!open) return null;

  return (
    <div
      className={`fixed inset-0 z-50 flex items-center justify-center bg-gray-500 bg-opacity-50 ${
        open ? 'animate-fadeIn' : 'animate-fadeOut'
      }`}
    >
      <div
        className={`bg-white rounded-lg shadow-lg w-11/12 max-w-md p-6 relative transform transition-transform duration-300 ${
          open ? 'scale-100' : 'scale-90'
        }`}
      >
        <header className='flex justify-between items-center mb-4'>
          <h2 className='text-2xl font-semibold'>{title}</h2>
          <button
            className='text-gray-500 hover:text-gray-700 text-xl'
            onClick={close}
          >
            &times;
          </button>
        </header>
        <main>{children}</main>
      </div>
    </div>
  );
}

 

 

모달의 기본적인 틀만 만들어 준 후 나머지는 모달을 사용하는 페이지에서 설정해주도록 한다. 

이 때 애니메이션의 fadeIn, fadeOut을 사용하기 위해 tailwind.config.js의 설정이 필요하다

 

// tailwind.config.js
module.exports = {
  content: ['./src/**/*.{js,jsx,ts,tsx}'], // 프로젝트 파일 경로
  theme: {
    extend: {
      keyframes: {
        fadeIn: {
          from: { opacity: '0' },
          to: { opacity: '1' },
        },
        fadeOut: {
          from: { opacity: '1' },
          to: { opacity: '0' },
        },
      },
      animation: {
        fadeIn: 'fadeIn 0.3s ease-in-out',
        fadeOut: 'fadeOut 0.3s ease-in-out',
      },
    },
  },
  plugins: [],
};

 

tailwind.config.js를 설정해주고 시작하도록 하자.

export default function Projects() {
  const [openModalId, setOpenModalId] = useState(null);

  const openModal = (id) => {
    setOpenModalId(id);
  };

  const closeModal = () => {
    setOpenModalId(null);
  };
  
   // 배경 스크롤 방지
  useEffect(() => {
    if (openModalId !== null) {
      document.body.style.overflow = 'hidden'; // 스크롤 비활성화
    } else {
      document.body.style.overflow = ''; // 스크롤 복원
    }

    return () => {
      document.body.style.overflow = ''; // 컴포넌트 언마운트 시 초기화
    };
  }, [openModalId]);

  const currentProject = projects.find((project) => project.id === openModalId);

 return (
    // ... project 영역 구현
    
    // 모달 렌더링
    {currentProject && (
      <Modal
        open={currentProject}
        close={closeModal}
        title={currentProject.title}
      >
        {currentProject.description}
      </Modal>
    )}
 )
}

 

각각의 카드를 만들고 project의 id에 해당하는 모달이 열릴 수 있도록 구현했다. 

반응형