File
Blob: src/client/components/ui/confirm-dialog.tsx
| 1 | import { type ReactNode } from "react"; |
| 2 | |
| 3 | import { Button } from "@/client/components/ui/button"; |
| 4 | import { Dialog } from "@/client/components/ui/dialog"; |
| 5 | |
| 6 | type Props = { |
| 7 | open: boolean; |
| 8 | onClose: () => void; |
| 9 | onConfirm: () => void; |
| 10 | title: ReactNode; |
| 11 | description?: ReactNode; |
| 12 | children?: ReactNode; |
| 13 | confirmLabel?: string; |
| 14 | cancelLabel?: string; |
| 15 | destructive?: boolean; |
| 16 | loading?: boolean; |
| 17 | }; |
| 18 | |
| 19 | export function ConfirmDialog({ |
| 20 | open, |
| 21 | onClose, |
| 22 | onConfirm, |
| 23 | title, |
| 24 | description, |
| 25 | children, |
| 26 | confirmLabel = "Confirm", |
| 27 | cancelLabel = "Cancel", |
| 28 | destructive = false, |
| 29 | loading = false, |
| 30 | }: Props) { |
| 31 | return ( |
| 32 | <Dialog |
| 33 | open={open} |
| 34 | onClose={() => { |
| 35 | if (!loading) onClose(); |
| 36 | }} |
| 37 | title={title} |
| 38 | size="sm" |
| 39 | closeOnBackdrop={!loading} |
| 40 | footer={ |
| 41 | <> |
| 42 | <Button variant="ghost" onClick={onClose} disabled={loading}> |
| 43 | {cancelLabel} |
| 44 | </Button> |
| 45 | <Button variant={destructive ? "danger" : "primary"} onClick={onConfirm} loading={loading}> |
| 46 | {confirmLabel} |
| 47 | </Button> |
| 48 | </> |
| 49 | } |
| 50 | > |
| 51 | {description || children ? ( |
| 52 | <div className="space-y-3"> |
| 53 | {description ? <p className="text-sm text-zinc-400">{description}</p> : null} |
| 54 | {children} |
| 55 | </div> |
| 56 | ) : null} |
| 57 | </Dialog> |
| 58 | ); |
| 59 | } |