react 에니메이션 modal 만들기

Stack

Nextjs
yarn berry
vanilla-extract

modal.tsx

import { useEffect, useState } from "react";
import { modalBodyRecipe, modalHeaderRecipe, modalOverlayRecipe, modalRecipe } from "./modal.css";

interface Props {
	show: boolean;
	onClose: () => void;
	title: string;
}

const Modal: React.FC<Props> = ({ show, onClose, children, title }) => {
	const [isBrowser, setIsBrowser] = useState(false);
	useEffect(() => {
		setIsBrowser(true);
	}, []);

	const handleCloseClick = (e: React.MouseEvent<HTMLSpanElement>) => {
		e.preventDefault();
		onClose();
	};

	const modalContent = (
		<div className={modalOverlayRecipe({ show })}>
			<div className={modalRecipe()}>
				<div className={modalHeaderRecipe()}>
					<span onClick={handleCloseClick}>x</span>
				</div>
				{title && <p>{title}</p>}
				<div className={modalBodyRecipe()}>{children}</div>
			</div>
		</div>
	);

	if (!isBrowser) return null;

	return modalContent;
};

export default Modal;

modal.css.ts

import { style } from "@vanilla-extract/css";
import { recipe } from "@vanilla-extract/recipes";

// modal
const modalBodyStyle = style({
	paddingTop: "10xp",
});

export const modalBodyRecipe = recipe({
	base: [modalBodyStyle],
	variants: {},
});

// header
const modalheaderStyle = style({
	display: "flex",
	justifyContent: "flex-end",
	fontSize: "25px",
});

export const modalHeaderRecipe = recipe({
	base: [modalheaderStyle],
	variants: {},
});

//
const modalStyle = style({
	backgroundColor: "white",
	width: "100%",
	maxWidth: "739px",
	height: "100%",
	borderRadius: "15px",
	padding: "15px",
});

export const modalRecipe = recipe({
	base: [modalStyle],
	variants: {},
});

// Overlay
const modalOverlayStyle = style({
	zIndex: "9999",
	position: "absolute",
	top: "0",
	left: "0",
	width: "100%",
	height: "100%",
	display: "flex",
	justifyContent: "center",
	alignItems: "center",
	backgroundColor: "rgba(0, 0, 0, 0.3)",
	transform: "translateY(110%)",
	transition: "transform 1s ease",
});

export const modalOverlayRecipe = recipe({
	base: [modalOverlayStyle],
	variants: {
		show: {
			true: {
				transform: "translateY(0)",
			},
			false: {
				transform: "translateY(110%)",
			},
		},
	},
});

결과 화면

후기

vanilla-extract 의 사용이 미숙해서 생각보다 시간이 많이 소요됐다

좋은 웹페이지 즐겨찾기