diff --git a/src/app/storybook/common-dialog/page.tsx b/src/app/storybook/common-dialog/page.tsx
new file mode 100644
index 00000000..d5935a72
--- /dev/null
+++ b/src/app/storybook/common-dialog/page.tsx
@@ -0,0 +1,70 @@
+"use client";
+import {
+ CommonDialogProvider,
+ useCommonDialog,
+} from "@/components/common-dialog";
+import { Button } from "@/components/ui/button";
+import { TrashIcon } from "lucide-react";
+
+function StorybookBody() {
+ const { showDialog } = useCommonDialog();
+
+ return (
+
+
+
+
+
+ );
+}
+
+export default function CommonDialogStorybook() {
+ return (
+
+
+
+ );
+}
diff --git a/src/components/common-dialog/index.tsx b/src/components/common-dialog/index.tsx
new file mode 100644
index 00000000..403a8be8
--- /dev/null
+++ b/src/components/common-dialog/index.tsx
@@ -0,0 +1,145 @@
+"use client";
+import { noop } from "lodash";
+import {
+ PropsWithChildren,
+ ReactElement,
+ createContext,
+ useCallback,
+ useContext,
+ useState,
+} from "react";
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+} from "../ui/dialog";
+import { Button } from "../ui/button";
+import { Icon } from "@phosphor-icons/react";
+import { Loader } from "lucide-react";
+import CodePreview from "../gui/code-preview";
+
+interface ShowDialogProps {
+ title: string;
+ content: string | ReactElement;
+ destructive?: boolean;
+ previewCode?: string;
+ actions?: {
+ text: string;
+ icon?: Icon;
+ onClick: () => Promise;
+ onComplete?: () => void;
+ }[];
+}
+
+interface CommonDialogContextProps {
+ showDialog(option: ShowDialogProps): void;
+}
+
+const CommonDialogContext = createContext({
+ showDialog: noop,
+});
+
+export function CommonDialogProvider({ children }: PropsWithChildren) {
+ const [dialogOption, setDialogOption] = useState(
+ null
+ );
+
+ const [errorMessage, setErrorMessage] = useState("");
+ const [loading, setLoading] = useState(false);
+
+ const hideDialog = useCallback(() => {
+ setErrorMessage("");
+ setDialogOption(null);
+ }, []);
+
+ return (
+
+ {children}
+ {dialogOption && (
+
+ )}
+
+ );
+}
+
+export function useCommonDialog() {
+ return useContext(CommonDialogContext);
+}
diff --git a/src/components/gui/studio.tsx b/src/components/gui/studio.tsx
index 7cb6d836..93c4f64e 100644
--- a/src/components/gui/studio.tsx
+++ b/src/components/gui/studio.tsx
@@ -9,6 +9,7 @@ import { StudioContextMenuItem } from "@/messages/open-context-menu";
import { CollaborationBaseDriver } from "@/drivers/collaboration-driver-base";
import { SavedDocDriver } from "@/drivers/saved-doc/saved-doc-driver";
import { FullEditorProvider } from "./providers/full-editor-provider";
+import { CommonDialogProvider } from "../common-dialog";
export interface StudioExtension {
contextMenu?: (state: OptimizeTableState) => StudioContextMenuItem[];
@@ -75,9 +76,11 @@ export function Studio({
onBack={onBack}
sideBarFooterComponent={sideBarFooterComponent}
>
-
-
-
+
+
+
+
+
);