Files

112 lines
3.0 KiB
TypeScript

"use client";
import { useRouter } from "next/navigation";
import { Dispatch, SetStateAction } from "react";
import * as Dialog from "@radix-ui/react-dialog";
import { Drawer } from "vaul";
import { cn } from "@/lib/utils";
import { useMediaQuery } from "@/lib/utils/use-media-query";
export function Modal({
children,
className,
showModal,
setShowModal,
onClose,
desktopOnly,
preventDefaultClose,
noBackdropBlur = false,
}: {
children: React.ReactNode;
className?: string;
showModal?: boolean;
setShowModal?: Dispatch<SetStateAction<boolean>>;
onClose?: () => void;
desktopOnly?: boolean;
preventDefaultClose?: boolean;
noBackdropBlur?: boolean;
}) {
const router = useRouter();
const closeModal = ({ dragged }: { dragged?: boolean } = {}) => {
if (preventDefaultClose && !dragged) {
return;
}
// fire onClose event if provided
onClose && onClose();
// if setShowModal is defined, use it to close modal
if (setShowModal) {
setShowModal(false);
// else, this is intercepting route @modal
} else {
router.back();
}
};
const { isMobile } = useMediaQuery();
if (isMobile && !desktopOnly) {
return (
<Drawer.Root
open={setShowModal ? showModal : true}
onOpenChange={(open) => {
if (!open) {
closeModal({ dragged: true });
}
}}
>
<Drawer.Overlay className="fixed inset-0 z-50 bg-background/80 backdrop-blur" />
<Drawer.Portal>
<Drawer.Content
className={cn(
"fixed bottom-0 left-0 right-0 z-50 mt-24 rounded-t-[10px] border-t border-gray-200 bg-background dark:border-gray-800 dark:bg-gray-900",
className,
)}
>
<div className="sticky top-0 z-20 flex w-full items-center justify-center rounded-t-[10px] bg-inherit">
<div className="my-3 h-1 w-12 rounded-full bg-gray-300" />
</div>
{children}
</Drawer.Content>
<Drawer.Overlay />
</Drawer.Portal>
</Drawer.Root>
);
}
return (
<Dialog.Root
open={setShowModal ? showModal : true}
onOpenChange={(open) => {
if (!open) {
closeModal();
}
}}
>
<Dialog.Portal>
<Dialog.Overlay
// for detecting when there's an active opened modal
id="modal-backdrop"
className={cn(
"fixed inset-0 z-50 animate-fade-in bg-background/80",
!noBackdropBlur && "backdrop-blur-md",
)} // backdrop-blur-md
/>
<Dialog.Content
onOpenAutoFocus={(e) => e.preventDefault()}
onCloseAutoFocus={(e) => e.preventDefault()}
className={cn(
"fixed inset-0 z-50 m-auto max-h-fit w-full max-w-md animate-scale-in overflow-hidden border border-gray-200 bg-background p-0 shadow-xl dark:border-gray-800 dark:bg-gray-900 sm:rounded-lg",
className,
)}
>
{children}
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
);
}