sitcod3 commited on
Commit
bd3ea9c
·
verified ·
1 Parent(s): 05126f3

Upload src/components/ConfirmModal.tsx with huggingface_hub

Browse files
Files changed (1) hide show
  1. src/components/ConfirmModal.tsx +113 -0
src/components/ConfirmModal.tsx ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Dialog, DialogPanel, DialogTitle, Transition, TransitionChild } from "@headlessui/react";
2
+ import { Fragment, ReactNode } from "react";
3
+ import { AlertTriangle, X } from "lucide-react";
4
+
5
+ interface ConfirmModalProps {
6
+ isOpen: boolean;
7
+ onClose: () => void;
8
+ onConfirm: () => void;
9
+ title: string;
10
+ description: string | ReactNode;
11
+ confirmText?: string;
12
+ cancelText?: string;
13
+ isDestructive?: boolean;
14
+ isLoading?: boolean;
15
+ }
16
+
17
+ export default function ConfirmModal({
18
+ isOpen,
19
+ onClose,
20
+ onConfirm,
21
+ title,
22
+ description,
23
+ confirmText = "Confirm",
24
+ cancelText = "Cancel",
25
+ isDestructive = true,
26
+ isLoading = false,
27
+ }: ConfirmModalProps) {
28
+ return (
29
+ <Transition appear show={isOpen} as={Fragment}>
30
+ <Dialog as="div" className="relative z-50" onClose={onClose}>
31
+ <TransitionChild
32
+ as={Fragment}
33
+ enter="ease-out duration-200"
34
+ enterFrom="opacity-0"
35
+ enterTo="opacity-100"
36
+ leave="ease-in duration-150"
37
+ leaveFrom="opacity-100"
38
+ leaveTo="opacity-0"
39
+ >
40
+ <div className="fixed inset-0 bg-black/70 backdrop-blur-xs" />
41
+ </TransitionChild>
42
+
43
+ <div className="fixed inset-0 overflow-y-auto">
44
+ <div className="flex min-h-full items-center justify-center p-4 text-center">
45
+ <TransitionChild
46
+ as={Fragment}
47
+ enter="ease-out duration-200"
48
+ enterFrom="opacity-0 scale-95"
49
+ enterTo="opacity-100 scale-100"
50
+ leave="ease-in duration-150"
51
+ leaveFrom="opacity-100 scale-100"
52
+ leaveTo="opacity-0 scale-95"
53
+ >
54
+ <DialogPanel className="w-full max-w-md transform overflow-hidden rounded-xl bg-zinc-900 border border-zinc-800 p-6 text-left align-middle shadow-2xl transition-all">
55
+ <div className="flex items-start gap-4">
56
+ <div
57
+ className={`p-3 rounded-full shrink-0 ${
58
+ isDestructive ? "bg-rose-500/10 text-rose-400 border border-rose-500/20" : "bg-indigo-500/10 text-indigo-400 border border-indigo-500/20"
59
+ }`}
60
+ >
61
+ <AlertTriangle className="w-6 h-6" />
62
+ </div>
63
+ <div className="flex-1 min-w-0">
64
+ <DialogTitle as="h3" className="text-lg font-semibold text-zinc-100">
65
+ {title}
66
+ </DialogTitle>
67
+ <div className="mt-2 text-sm text-zinc-400">
68
+ {description}
69
+ </div>
70
+ </div>
71
+ <button
72
+ onClick={onClose}
73
+ className="text-zinc-500 hover:text-zinc-300 transition-colors p-1 rounded-md"
74
+ >
75
+ <X className="w-5 h-5" />
76
+ </button>
77
+ </div>
78
+
79
+ <div className="mt-6 flex justify-end gap-3">
80
+ <button
81
+ type="button"
82
+ onClick={onClose}
83
+ disabled={isLoading}
84
+ className="px-4 py-2 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 text-sm font-medium rounded-lg transition-colors"
85
+ >
86
+ {cancelText}
87
+ </button>
88
+ <button
89
+ type="button"
90
+ onClick={() => {
91
+ onConfirm();
92
+ }}
93
+ disabled={isLoading}
94
+ className={`px-4 py-2 text-sm font-medium rounded-lg text-white transition-colors flex items-center gap-2 ${
95
+ isDestructive
96
+ ? "bg-rose-600 hover:bg-rose-500"
97
+ : "bg-indigo-600 hover:bg-indigo-500"
98
+ } disabled:opacity-50`}
99
+ >
100
+ {isLoading && (
101
+ <div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
102
+ )}
103
+ {confirmText}
104
+ </button>
105
+ </div>
106
+ </DialogPanel>
107
+ </TransitionChild>
108
+ </div>
109
+ </div>
110
+ </Dialog>
111
+ </Transition>
112
+ );
113
+ }