diff --git a/frontend/app/modals/confirmclosetab.tsx b/frontend/app/modals/confirmclosetab.tsx new file mode 100644 index 000000000..a431fcb45 --- /dev/null +++ b/frontend/app/modals/confirmclosetab.tsx @@ -0,0 +1,39 @@ +// Copyright 2025, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import { Modal } from "@/app/modals/modal"; +import { deleteLayoutModelForTab } from "@/layout/index"; +import { atoms, getApi, globalStore } from "@/store/global"; +import { modalsModel } from "@/store/modalmodel"; + +interface ConfirmCloseTabModalProps { + tabId: string; +} + +const ConfirmCloseTabModal = ({ tabId }: ConfirmCloseTabModalProps) => { + const handleConfirmClose = () => { + const ws = globalStore.get(atoms.workspace); + getApi().closeTab(ws.oid, tabId); + deleteLayoutModelForTab(tabId); + modalsModel.popModal(); + }; + + const handleCancel = () => { + modalsModel.popModal(); + }; + + return ( + +
+
Close Tab?
+
+ Are you sure you want to close this tab? This action cannot be undone. +
+
+
+ ); +}; + +ConfirmCloseTabModal.displayName = "ConfirmCloseTabModal"; + +export { ConfirmCloseTabModal }; diff --git a/frontend/app/modals/modalregistry.tsx b/frontend/app/modals/modalregistry.tsx index 53fabde06..a19cb4704 100644 --- a/frontend/app/modals/modalregistry.tsx +++ b/frontend/app/modals/modalregistry.tsx @@ -7,6 +7,7 @@ import { UpgradeOnboardingModal } from "@/app/onboarding/onboarding-upgrade"; import { DeleteFileModal, PublishAppModal, RenameFileModal } from "@/builder/builder-apppanel"; import { SetSecretDialog } from "@/builder/tabs/builder-secrettab"; import { AboutModal } from "./about"; +import { ConfirmCloseTabModal } from "./confirmclosetab"; import { UserInputModal } from "./userinputmodal"; const modalRegistry: { [key: string]: React.ComponentType } = { @@ -15,6 +16,7 @@ const modalRegistry: { [key: string]: React.ComponentType } = { [UserInputModal.displayName || "UserInputModal"]: UserInputModal, [AboutModal.displayName || "AboutModal"]: AboutModal, [MessageModal.displayName || "MessageModal"]: MessageModal, + [ConfirmCloseTabModal.displayName || "ConfirmCloseTabModal"]: ConfirmCloseTabModal, [PublishAppModal.displayName || "PublishAppModal"]: PublishAppModal, [RenameFileModal.displayName || "RenameFileModal"]: RenameFileModal, [DeleteFileModal.displayName || "DeleteFileModal"]: DeleteFileModal, diff --git a/frontend/app/tab/tabbar.tsx b/frontend/app/tab/tabbar.tsx index 2a479aa63..7831fda1d 100644 --- a/frontend/app/tab/tabbar.tsx +++ b/frontend/app/tab/tabbar.tsx @@ -620,10 +620,9 @@ const TabBar = memo(({ workspace }: TabBarProps) => { const handleCloseTab = (event: React.MouseEvent | null, tabId: string) => { event?.stopPropagation(); - const ws = globalStore.get(atoms.workspace); - getApi().closeTab(ws.oid, tabId); - tabsWrapperRef.current.style.setProperty("--tabs-wrapper-transition", "width 0.3s ease"); - deleteLayoutModelForTab(tabId); + + // Show confirmation modal before closing + modalsModel.pushModal("ConfirmCloseTabModal", { tabId }); }; const handlePinChange = useCallback(