6 changed files with 100 additions and 67 deletions
@ -1,50 +0,0 @@ |
|||||||
import { ReactNode } from "react"; |
|
||||||
import { createPortal } from "react-dom"; |
|
||||||
|
|
||||||
import { Overlay } from "@/components/Overlay"; |
|
||||||
import { Transition } from "@/components/Transition"; |
|
||||||
|
|
||||||
interface Props { |
|
||||||
show: boolean; |
|
||||||
children?: ReactNode; |
|
||||||
} |
|
||||||
|
|
||||||
export function ModalFrame(props: Props) { |
|
||||||
return ( |
|
||||||
<Transition |
|
||||||
className="fixed inset-0 z-[9999]" |
|
||||||
animation="none" |
|
||||||
show={props.show} |
|
||||||
> |
|
||||||
<Overlay> |
|
||||||
<Transition |
|
||||||
isChild |
|
||||||
className="flex h-full w-full items-center justify-center" |
|
||||||
animation="slide-up" |
|
||||||
> |
|
||||||
{props.children} |
|
||||||
</Transition> |
|
||||||
</Overlay> |
|
||||||
</Transition> |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
export function Modal(props: Props) { |
|
||||||
return createPortal( |
|
||||||
<ModalFrame show={props.show}>{props.children}</ModalFrame>, |
|
||||||
document.body |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
export function ModalCard(props: { className?: string; children?: ReactNode }) { |
|
||||||
return ( |
|
||||||
<div |
|
||||||
className={[ |
|
||||||
"relative mx-2 w-[500px] overflow-hidden rounded-lg bg-denim-300 px-10 py-10 sm:w-[500px] md:w-[500px] lg:w-[1000px]", |
|
||||||
props.className ?? "", |
|
||||||
].join(" ")} |
|
||||||
> |
|
||||||
{props.children} |
|
||||||
</div> |
|
||||||
); |
|
||||||
} |
|
@ -0,0 +1,42 @@ |
|||||||
|
import { ReactNode, useCallback } from "react"; |
||||||
|
import { Helmet } from "react-helmet-async"; |
||||||
|
|
||||||
|
import { OverlayPortal } from "@/components/overlays/OverlayDisplay"; |
||||||
|
import { useQueryParam } from "@/hooks/useQueryParams"; |
||||||
|
|
||||||
|
export function useModal(id: string) { |
||||||
|
const [currentModal, setCurrentModal] = useQueryParam("m"); |
||||||
|
const show = useCallback(() => setCurrentModal(id), [id, setCurrentModal]); |
||||||
|
const hide = useCallback(() => setCurrentModal(null), [setCurrentModal]); |
||||||
|
return { |
||||||
|
id, |
||||||
|
isShown: currentModal === id, |
||||||
|
show, |
||||||
|
hide, |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
export function ModalCard(props: { children?: ReactNode }) { |
||||||
|
return ( |
||||||
|
<div className="w-[30rem] max-w-full"> |
||||||
|
<div className="w-full bg-dropdown-background rounded-xl p-8 m-4 pointer-events-auto"> |
||||||
|
{props.children} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
export function Modal(props: { id: string; children?: ReactNode }) { |
||||||
|
const modal = useModal(props.id); |
||||||
|
|
||||||
|
return ( |
||||||
|
<OverlayPortal darken close={modal.hide} show={modal.isShown}> |
||||||
|
<Helmet> |
||||||
|
<html data-no-scroll /> |
||||||
|
</Helmet> |
||||||
|
<div className="flex absolute inset-0 items-center justify-center flex-col"> |
||||||
|
{props.children} |
||||||
|
</div> |
||||||
|
</OverlayPortal> |
||||||
|
); |
||||||
|
} |
Loading…
Reference in new issue