Displays a modal for searching and selecting AniList manga matches for a given Kenmei manga.

export const SearchModal: React.FC<SearchModalProps> = ({
isOpen,
searchTarget,
accessToken,
bypassCache,
onClose,
onSelectMatch,
}) => {
useEffect(() => {
if (!isOpen) {
return;
}

if (globalThis.window === undefined || typeof document === "undefined") {
return;
}

const previousOverflow = document.body.style.overflow;
const previousPaddingRight = document.body.style.paddingRight;
const previousScrollBehavior = document.body.style.scrollBehavior;

const scrollbarWidth =
window.innerWidth - document.documentElement.clientWidth;

document.body.style.overflow = "hidden";
if (scrollbarWidth > 0) {
document.body.style.paddingRight = `${scrollbarWidth}px`;
}
document.body.style.scrollBehavior = "auto";

return () => {
document.body.style.overflow = previousOverflow;
document.body.style.paddingRight = previousPaddingRight;
document.body.style.scrollBehavior = previousScrollBehavior;
};
}, [isOpen]);

const portalTarget =
globalThis.window !== undefined && typeof document !== "undefined"
? document.body
: null;

if (!portalTarget) {
return null;
}

// Don't return null; let AnimatePresence handle the transition
return createPortal(
<AnimatePresence>
{isOpen && searchTarget && (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4">
{/* Blurred backdrop */}
<motion.div
className="fixed inset-0 bg-slate-950/65 backdrop-blur-2xl transition-all"
onClick={onClose}
aria-hidden="true"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.2 }}
></motion.div>

<motion.div
className="relative z-50 m-4 max-h-[85vh] w-full max-w-6xl overflow-visible rounded-[32px] border border-white/15 bg-gradient-to-br from-blue-400/25 via-white/15 to-purple-500/20 p-[1.5px] shadow-[0_40px_160px_-60px_rgba(30,64,175,0.7)] backdrop-blur-2xl dark:border-slate-700/40"
initial={{ opacity: 0, y: 20, scale: 0.98 }}
animate={{ opacity: 1, y: 0, scale: 1 }}
exit={{ opacity: 0, y: -20, scale: 0.98 }}
transition={{
duration: 0.25,
type: "spring",
stiffness: 400,
damping: 30,
}}
>
<div className="max-h-[85vh] overflow-auto rounded-[30px] bg-white/90 p-2 shadow-[inset_0_0_1px_rgba(255,255,255,0.4)] dark:bg-slate-950/85">
<MangaSearchPanel
key={`search-${searchTarget.id}`}
kenmeiManga={searchTarget}
onClose={onClose}
onSelectMatch={onSelectMatch}
token={accessToken || ""}
bypassCache={bypassCache}
/>
</div>
</motion.div>
</div>
)}
</AnimatePresence>,
portalTarget,
);
};
<SearchModal isOpen={isOpen} searchTarget={manga} accessToken={token} bypassCache={false} onClose={handleClose} onSelectMatch={handleSelect} />