diff --git a/src/components/common/Portal.tsx b/src/components/common/Portal.tsx
new file mode 100644
index 00000000..2c5c0cc4
--- /dev/null
+++ b/src/components/common/Portal.tsx
@@ -0,0 +1,48 @@
+import { PropsWithChildren, createContext, useContext, useMemo } from "react"
+import { createPortal } from "react-dom"
+
+import { useIsClient } from "~/hooks/useClient"
+import { isServerSide } from "~/lib/utils"
+
+export const usePortal = () => {
+ const ctx = useContext(RootPortalContext)
+ if (isServerSide()) {
+ return null
+ }
+ return ctx.to || document.body
+}
+
+const RootPortalContext = createContext<{
+ to?: HTMLElement | undefined
+}>({
+ to: undefined,
+})
+export const PortalProvider = (
+ props: PropsWithChildren<{
+ to: HTMLElement
+ }>,
+) => (
+
({
+ to: props.to,
+ }),
+ [props.to],
+ )}
+ >
+ {props.children}
+
+)
+
+export const Portal = (
+ props: PropsWithChildren<{
+ to?: HTMLElement
+ }>,
+) => {
+ const client = useIsClient()
+ const to = usePortal()
+
+ if (!client) return null
+
+ return createPortal(props.children, props.to || to || document.body)
+}
diff --git a/src/components/ui/Modal.tsx b/src/components/ui/Modal.tsx
index 6c11cee4..65e496ab 100644
--- a/src/components/ui/Modal.tsx
+++ b/src/components/ui/Modal.tsx
@@ -1,11 +1,11 @@
import clsx from "clsx"
-import React from "react"
+import React, { forwardRef } from "react"
import { Dialog } from "@headlessui/react"
import { cn } from "~/lib/utils"
-export const Modal: React.FC<{
+interface ModalProps {
open: boolean
setOpen: (open: boolean) => void
children: React.ReactNode
@@ -13,49 +13,58 @@ export const Modal: React.FC<{
titleIcon?: React.ReactNode
size?: "md" | "lg" | "sm"
zIndex?: number
-}> = ({ open, setOpen, children, title, titleIcon, size = "md", zIndex }) => {
- return (
-
- )
}
+
+export const Modal = forwardRef
(
+ ({ open, setOpen, children, title, titleIcon, size = "md", zIndex }, ref) => {
+ return (
+
+ )
+ },
+)
+
+Modal.displayName = "Modal"
diff --git a/src/hooks/useClient.ts b/src/hooks/useClient.ts
new file mode 100644
index 00000000..560c48ac
--- /dev/null
+++ b/src/hooks/useClient.ts
@@ -0,0 +1,10 @@
+import { useEffect, useState } from "react"
+
+export const useIsClient = () => {
+ const [isClient, setIsClient] = useState(false)
+
+ useEffect(() => {
+ setIsClient(true)
+ }, [])
+ return isClient
+}