Skip to content

Commit b2f781c

Browse files
committed
feat: add mounting logic and portal rendering to FinalOutputView component
1 parent ee2d19b commit b2f781c

File tree

1 file changed

+23
-2
lines changed

1 file changed

+23
-2
lines changed

components/final-output-view.tsx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"use client"
22

33
import { useCallback, useEffect, useMemo, useRef, useState } from "react"
4+
import { createPortal } from "react-dom"
45
import type { ChangeEvent, MouseEvent } from "react"
56
import { Copy, Download, X } from "lucide-react"
67

@@ -15,6 +16,7 @@ export default function FinalOutputView({ fileName, fileContent, mimeType, onClo
1516
const dialogRef = useRef<HTMLDivElement | null>(null)
1617
const [baselineContent, setBaselineContent] = useState(fileContent ?? "")
1718
const [currentContent, setCurrentContent] = useState(fileContent ?? "")
19+
const [isMounted, setIsMounted] = useState(false)
1820

1921
const normalizedFileName = useMemo(() => {
2022
const trimmed = fileName?.trim()
@@ -36,6 +38,18 @@ export default function FinalOutputView({ fileName, fileContent, mimeType, onClo
3638
}, [baselineContent, normalizedFileName])
3739

3840
useEffect(() => {
41+
setIsMounted(true)
42+
43+
return () => {
44+
setIsMounted(false)
45+
}
46+
}, [])
47+
48+
useEffect(() => {
49+
if (!isMounted) {
50+
return undefined
51+
}
52+
3953
const previousOverflow = document.body.style.overflow
4054
document.body.style.overflow = "hidden"
4155

@@ -52,10 +66,11 @@ export default function FinalOutputView({ fileName, fileContent, mimeType, onClo
5266
if (resetTimerRef.current !== null) {
5367
window.clearTimeout(resetTimerRef.current)
5468
}
69+
5570
document.body.style.overflow = previousOverflow
5671
window.removeEventListener("keydown", handleKeyDown)
5772
}
58-
}, [onClose])
73+
}, [onClose, isMounted])
5974

6075
const handleCopyClick = useCallback(async () => {
6176
if (!currentContent) {
@@ -135,7 +150,7 @@ export default function FinalOutputView({ fileName, fileContent, mimeType, onClo
135150
const displayedContent = currentContent && currentContent.length > 0 ? currentContent : ""
136151
const restoreDisabled = displayedContent === baselineContent
137152

138-
return (
153+
const modalContent = (
139154
<div
140155
className="fixed inset-0 z-50 flex items-center justify-center bg-background/80 p-4 backdrop-blur-sm overscroll-contain"
141156
role="dialog"
@@ -213,4 +228,10 @@ export default function FinalOutputView({ fileName, fileContent, mimeType, onClo
213228
</div>
214229
</div>
215230
)
231+
232+
if (!isMounted || typeof document === "undefined") {
233+
return null
234+
}
235+
236+
return createPortal(modalContent, document.body)
216237
}

0 commit comments

Comments
 (0)