모달을 조건부 렌더링으로 구현했지만, 애니메이션 효과가 없어 UI가 너무 딱딱하게 느껴졌다.
검색을 통해 대부분의 구현이 opacity
속성을 이용해 모달을 투명하게 만들고, 클릭 시 보이게 하는 방법을 사용한다는 것을 알게 되었습니다. 그러나 여러 시행착오 끝에 @keyframes
와 animation
속성을 이용해 모달에 애니메이션을 추가하여 문제를 해결했습니다.
pointer-events: none
속성을 사용할 수 있지만, 이 경우 백그라운드 클릭으로 모달을 닫을 수 없으며, 모달 내부의 버튼도 사용할 수 없게 됩니다.모달을 보다 효율적으로 제어하기 위해 커스텀 훅을 사용하여 props 없이도 모달을 제어할 수 있도록 구현했습니다. 또한, 모달이 생성되면 백그라운드 클릭 또는 닫기 버튼(x)
을 눌러 모달이 사라지도록 기능을 추가했습니다.
// Modal.tsx
import React from 'react';
import { useModal } from './useModal';
const Header = () => {
const { clickHandler } = useModal();
return (
<LoginSection>
<p className="login" onClick={() => clickHandler(true)}>
로그인
</p>
</LoginSection>
);
};
const Modal = () => {
const { isOpen, clickHandler } = useModal();
return (
<Container display={isOpen ? 'flex' : 'none'}>
{/* 모달 백그라운드 클릭 시 모달 닫기 */}
<ModalBackground onClick={() => clickHandler(false)} />
<ModalWindow>
{/* x 버튼 클릭 시 모달 닫기 */}
<p className="close" onClick={() => clickHandler(false)}>
×
</p>
</ModalWindow>
</Container>
);
};
// useModal.ts
import { useState } from 'react';
// 모달을 제어하는 커스텀 훅
export const useModal = () => {
const [isOpen, setIsOpen] = useState(false);
// 클릭 시 모달 열기/닫기 제어
const clickHandler = (isClicked: boolean) => {
setIsOpen(isClicked);
};
return { isOpen, clickHandler };
};
모달이 부드럽게 나타나고 사라지도록 애니메이션을 추가했습니다. 백그라운드를 클릭했을 때도 모달이 사라지도록 설정했습니다.
// modalstyled.ts
const Container = styled.div`
display: ${(props) => props.display || 'none'};
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.6);
`;
const ModalBackground = styled.div`
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
`;
// 모달 애니메이션 설정
const ModalWindow = styled.div`
position: relative;
width: 380px;
height: 550px;
background: white;
padding: 0 30px;
animation: modaldown 0.5s linear;
@keyframes modaldown {
from {
transform: translateY(-10%);
}
to {
transform: translateY(0);
}
}
.close {
position: absolute;
right: 15px;
top: 5px;
cursor: pointer;
font-size: 25px;
}
`;
animation: modaldown 0.5s linear;
는 애니메이션의 이름과 지속 시간을 설정하는 부분입니다.from
은 애니메이션 시작 지점을, to
는 종료 지점을 나타냅니다. transform: translateY(-10%)
으로 모달이 약간 위에서 시작해 translateY(0)
으로 원래 위치에 오도록 설정했습니다.결과적으로 원하는 애니메이션 효과가 잘 구현되었습니다.