From fc0e913b8aa92441dedb4689fa868aadc07bee8d Mon Sep 17 00:00:00 2001 From: SeongHyun Kim Date: Mon, 23 Feb 2026 14:03:55 +0900 Subject: [PATCH] =?UTF-8?q?fix(pop-modal):=20=EC=A4=91=EC=B2=A9=20?= =?UTF-8?q?=EB=AA=A8=EB=8B=AC=20=EB=8B=AB=EA=B8=B0=20=EC=8B=9C=20=EB=AA=A8?= =?UTF-8?q?=EB=93=A0=20=EB=AA=A8=EB=8B=AC=EC=9D=B4=20=ED=95=9C=EA=BA=BC?= =?UTF-8?q?=EB=B2=88=EC=97=90=20=EB=8B=AB=ED=9E=88=EB=8A=94=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - handleCloseModal(index) -> handleCloseTopModal()로 변경 (최상위 1개만 닫기) - onOpenChange에 isTopModal 가드 추가 (하위 모달 연쇄 반응 방지) - onInteractOutside/onEscapeKeyDown에 isTopModal 가드 추가 Co-authored-by: Cursor --- .../pop/viewer/PopViewerWithModals.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/frontend/components/pop/viewer/PopViewerWithModals.tsx b/frontend/components/pop/viewer/PopViewerWithModals.tsx index 3e6a92a1..7e75672d 100644 --- a/frontend/components/pop/viewer/PopViewerWithModals.tsx +++ b/frontend/components/pop/viewer/PopViewerWithModals.tsx @@ -91,9 +91,9 @@ export default function PopViewerWithModals({ }; }, [subscribe, layout.modals]); - // 특정 인덱스의 모달 닫기 - const handleCloseModal = useCallback((index: number) => { - setModalStack(prev => prev.slice(0, index)); + // 최상위 모달만 닫기 (X 버튼, overlay 클릭, ESC) + const handleCloseTopModal = useCallback(() => { + setModalStack(prev => prev.slice(0, -1)); }, []); return ( @@ -112,10 +112,10 @@ export default function PopViewerWithModals({ {/* 모달 스택 렌더링 */} {modalStack.map((modal, index) => { const { definition } = modal; + const isTopModal = index === modalStack.length - 1; const closeOnOverlay = definition.frameConfig?.closeOnOverlay !== false; const closeOnEsc = definition.frameConfig?.closeOnEsc !== false; - // 모달의 layout 구성 (모달 자체를 하나의 레이아웃으로) const modalLayout: PopLayoutDataV5 = { ...layout, gridConfig: definition.gridConfig, @@ -123,7 +123,6 @@ export default function PopViewerWithModals({ overrides: definition.overrides, }; - // sizeConfig 기반 모달 너비 계산 const detectedMode = currentMode || detectGridMode(viewportWidth); const modalWidth = resolveModalWidth(definition.sizeConfig, detectedMode, viewportWidth); const isFull = modalWidth >= viewportWidth; @@ -134,7 +133,7 @@ export default function PopViewerWithModals({ key={`${definition.id}-${index}`} open={true} onOpenChange={(open) => { - if (!open) handleCloseModal(index); + if (!open && isTopModal) handleCloseTopModal(); }} > { - if (!closeOnOverlay) e.preventDefault(); + // 최상위 모달이 아니면 overlay 클릭 무시 (하위 모달이 먼저 닫히는 것 방지) + if (!isTopModal || !closeOnOverlay) e.preventDefault(); }} onEscapeKeyDown={(e) => { - if (!closeOnEsc) e.preventDefault(); + if (!isTopModal || !closeOnEsc) e.preventDefault(); }} >