summaryrefslogtreecommitdiff
path: root/components/ui/action-dialog.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'components/ui/action-dialog.tsx')
-rw-r--r--components/ui/action-dialog.tsx54
1 files changed, 54 insertions, 0 deletions
diff --git a/components/ui/action-dialog.tsx b/components/ui/action-dialog.tsx
new file mode 100644
index 00000000..9927bcc5
--- /dev/null
+++ b/components/ui/action-dialog.tsx
@@ -0,0 +1,54 @@
+"use client"
+
+import * as React from "react"
+import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogClose } from "@/components/ui/dialog"
+import { Button } from "@/components/ui/button"
+import { Loader } from "lucide-react"
+
+interface ActionConfirmDialogProps {
+ open: boolean
+ onOpenChange: (open: boolean) => void
+ title: string
+ description?: string
+ confirmLabel?: string
+ confirmVariant?: "default" | "destructive" | "outline" | "secondary" | "ghost"
+ onConfirm: () => Promise<void> | void
+ isLoading?: boolean
+}
+
+export function ActionConfirmDialog({
+ open,
+ onOpenChange,
+ title,
+ description,
+ confirmLabel = "Confirm",
+ confirmVariant = "destructive",
+ onConfirm,
+ isLoading,
+}: ActionConfirmDialogProps) {
+ return (
+ <Dialog open={open} onOpenChange={onOpenChange}>
+ <DialogContent>
+ <DialogHeader>
+ <DialogTitle>{title}</DialogTitle>
+ {description ? <DialogDescription>{description}</DialogDescription> : null}
+ </DialogHeader>
+ <DialogFooter className="gap-2">
+ <DialogClose asChild>
+ <Button variant="outline">Cancel</Button>
+ </DialogClose>
+ <Button
+ variant={confirmVariant}
+ onClick={onConfirm}
+ disabled={isLoading}
+ >
+ {isLoading && (
+ <Loader className="mr-2 size-4 animate-spin" aria-hidden="true" />
+ )}
+ {confirmLabel}
+ </Button>
+ </DialogFooter>
+ </DialogContent>
+ </Dialog>
+ )
+} \ No newline at end of file