Files
OpenSign/apps/OpenSign/src/primitives/ModalUi.jsx
T
2026-05-15 15:44:29 +00:00

103 lines
3.2 KiB
React

import { useEffect, useRef } from "react";
import { useTranslation } from "react-i18next";
import "../styles/signature.css";
import Loader from "./Loader";
import Tooltip from "./Tooltip";
const ModalUi = ({
id,
children,
title,
isOpen,
handleClose,
showHeader = true,
showClose = true,
reduceWidth,
position,
crossColor,
showScrollBar = false,
isLoader = false,
helpText = ""
}) => {
const { t } = useTranslation();
const dialogRef = useRef(null);
const width = reduceWidth;
const isBottom = position === "bottom" ? "items-end pb-2 !bg-black/10" : "";
const crossBtnColor = crossColor ?? "text-base-content";
const hideScrollBar = !showScrollBar ? "hide-scrollbar" : "";
// Keep bottom-sheet modals above the mobile virtual keyboard by tracking the
// visual viewport (which shrinks when the keyboard opens) and adjusting the
// dialog's height/top to match, so the modal never slides behind the keyboard.
useEffect(() => {
if (!isOpen || position !== "bottom" || !window.visualViewport) return;
const vp = window.visualViewport;
const updatePosition = () => {
if (!dialogRef.current) return;
dialogRef.current.style.height = `${vp.height}px`;
dialogRef.current.style.top = `${vp.offsetTop}px`;
};
updatePosition();
vp.addEventListener("resize", updatePosition);
vp.addEventListener("scroll", updatePosition);
return () => {
vp.removeEventListener("resize", updatePosition);
vp.removeEventListener("scroll", updatePosition);
};
}, [isOpen, position]);
return (
<>
{isOpen && (
<dialog
ref={dialogRef}
id={id || "selectSignerModal"}
className={`${isBottom} op-modal op-modal-open`}
style={{
overlay: { zIndex: 1000 },
content: { zIndex: 1001, overflow: "visible" } // Ensure modal doesn't clip content
}}
>
{isLoader && (
<div className="absolute z-[999] h-full w-full flex justify-center items-center bg-black bg-opacity-30">
<Loader />
</div>
)}
<div
className={`${width || "md:min-w-[500px]"} op-modal-box p-0 max-h-90 overflow-y-auto ${hideScrollBar} text-sm`}
>
{showHeader && (
<>
{title && (
<h3 className="text-base-content text-left font-bold text-lg pt-[15px] px-[20px]">
{title}
{helpText && (
<span className="ml-0.5 text-sm font-medium">
<Tooltip id={title} message={t(helpText)} />
</span>
)}
</h3>
)}
{showClose && (
<button
className={`${crossBtnColor} op-btn op-btn-sm op-btn-circle op-btn-ghost absolute right-2 top-2 z-40`}
onClick={() => handleClose && handleClose()}
>
</button>
)}
</>
)}
<div>{children}</div>
</div>
</dialog>
)}
</>
);
};
export default ModalUi;