feat(ui): add shared ConfirmDialog component
This commit is contained in:
@@ -0,0 +1,79 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { Loader2 } from "lucide-react"
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Modal } from "./modal"
|
||||||
|
|
||||||
|
export interface ConfirmDialogProps {
|
||||||
|
open: boolean
|
||||||
|
onClose: () => void
|
||||||
|
onConfirm: () => void
|
||||||
|
title?: string
|
||||||
|
message?: string
|
||||||
|
confirmLabel?: string
|
||||||
|
cancelLabel?: string
|
||||||
|
variant?: "default" | "destructive"
|
||||||
|
loading?: boolean
|
||||||
|
children?: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ConfirmDialog({
|
||||||
|
open,
|
||||||
|
onClose,
|
||||||
|
onConfirm,
|
||||||
|
title = "Confirm",
|
||||||
|
message,
|
||||||
|
confirmLabel = "Confirm",
|
||||||
|
cancelLabel = "Cancel",
|
||||||
|
variant = "default",
|
||||||
|
loading = false,
|
||||||
|
children,
|
||||||
|
}: ConfirmDialogProps) {
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
isOpen={open}
|
||||||
|
onClose={loading ? () => {} : onClose}
|
||||||
|
title={title}
|
||||||
|
size="sm"
|
||||||
|
showCloseButton={!loading}
|
||||||
|
>
|
||||||
|
<div className="space-y-4">
|
||||||
|
{message && (
|
||||||
|
<p className="text-sm text-text/80">{message}</p>
|
||||||
|
)}
|
||||||
|
{children}
|
||||||
|
<div className="flex items-center justify-end gap-3">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={onClose}
|
||||||
|
disabled={loading}
|
||||||
|
className={cn(
|
||||||
|
"inline-flex touch-target items-center justify-center rounded-md px-4 py-2 text-sm font-medium transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50",
|
||||||
|
"bg-text/10 text-text hover:bg-text/20",
|
||||||
|
loading && "opacity-70 cursor-not-allowed"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{cancelLabel}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={onConfirm}
|
||||||
|
disabled={loading}
|
||||||
|
className={cn(
|
||||||
|
"inline-flex touch-target items-center justify-center rounded-md px-4 py-2 text-sm font-medium transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50",
|
||||||
|
variant === "destructive"
|
||||||
|
? "bg-red-600 text-white hover:bg-red-700"
|
||||||
|
: "bg-primary text-white hover:bg-primary/90",
|
||||||
|
loading && "opacity-70 cursor-not-allowed"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{loading && (
|
||||||
|
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||||
|
)}
|
||||||
|
{confirmLabel}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1 +1,2 @@
|
|||||||
export { Modal } from "./modal"
|
export { Modal } from "./modal"
|
||||||
|
export { ConfirmDialog } from "./confirm-dialog"
|
||||||
|
|||||||
Reference in New Issue
Block a user