add model

This commit is contained in:
Виталий Лавшонок
2025-11-03 18:48:27 +03:00
parent f2ec4653bb
commit 91aa3e1f80
2 changed files with 88 additions and 2 deletions

View File

@@ -0,0 +1,79 @@
import React from "react";
import { motion, AnimatePresence } from "framer-motion";
import { cn } from "../../lib/cn";
import { useClickOutside } from "../../hooks/useClickOutside";
type ModalBackdrop = "opaque" | "blur";
interface ModalProps {
className?: string;
children?: React.ReactNode;
backdrop?: ModalBackdrop;
open: boolean;
defaultOpen?: boolean;
onOpenChange: (state: boolean) => void;
}
const modalbgVariants = {
closed: { opacity: 0 },
open: { opacity: 1 },
};
const modalVariants = {
closed: { opacity: 0, scale: 0.9 },
open: { opacity: 1, scale: 1 },
};
export const Modal: React.FC<ModalProps> = ({
children,
open,
backdrop,
className,
onOpenChange,
}) => {
const ref = React.useRef<HTMLDivElement>(null);
useClickOutside(ref, () => {
onOpenChange(false);
});
return (
<div>
<AnimatePresence>
{open && (
<motion.div
initial={modalbgVariants.closed}
animate={modalbgVariants.open}
exit={modalbgVariants.closed}
transition={{ duration: 0.15 }}
className={cn(
" fixed top-0 left-0 h-svh w-svw backdrop-filter transition-all z-50",
// " pointer-events-none",
backdrop == "blur" && open ? "backdrop-blur-sm" : "",
backdrop == "opaque" && open ? "bg-[#00000055]" : ""
)}
></motion.div>
)}
</AnimatePresence>
<div className="fixed top-0 left-0 h-svh w-svw flex items-center justify-center pointer-events-none z-50">
<AnimatePresence>
{open && (
<motion.div
ref={ref}
className={cn(
"h-fit w-fit rounded-md pointer-events-auto",
className
)}
initial={modalVariants.closed}
animate={modalVariants.open}
exit={modalVariants.closed}
transition={{ duration: 0.15 }}
>
{children}
</motion.div>
)}
</AnimatePresence>
</div>
</div>
);
};