Confirm Dialog
WhereUIกล่องยืนยันการกระทำบน AlertDialog รองรับ variant แบบทำลายล้าง ปรับข้อความปุ่มได้ และมีสถานะกำลังทำงาน
ติดตั้ง
Terminal
pnpm dlx shadcn@latest add @whereui/confirm-dialogต้องผูก registry และติดตั้ง @whereui/theme นำหน้าเสมอเมื่อติดตั้งครั้งแรก
การใช้งาน
import { ConfirmDialog } from "@/components/ui/confirm-dialog"const [open, setOpen] = React.useState(false)<ConfirmDialog open={open} onOpenChange={setOpen} title="ยืนยันการส่งคำขอ?" description="หลังส่งแล้วจะแก้ไขไม่ได้" onConfirm={() => setOpen(false)}/>ตัวอย่างเพิ่มเติม
แบบปกติ (ไม่ใช่ลบ)
Props
| prop | type | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
| open | boolean | — | ควบคุมการแสดงผล (controlled) ผ่าน onOpenChange |
| onOpenChange | (open: boolean) => void | — | ถูกเรียกเมื่อปิด เช่น กดปุ่มยกเลิก Esc หรือคลิกนอกกล่อง |
| title | React.ReactNode | — | คำถามยืนยัน เช่น "ลบพนักงานคนนี้?" |
| description | React.ReactNode | — | รายละเอียดผลที่จะตามมา |
| confirmLabel / cancelLabel | string | "ยืนยัน" / "ยกเลิก" | ข้อความปุ่มทั้งสอง |
| variant | "default" | "destructive" | "default" | destructive = หัวเรื่องและปุ่มยืนยันเป็นสีแดง |
| loading | boolean | false | กำลังทำงาน — ปุ่มยืนยันมีตัวหมุน ปุ่มทั้งคู่กดไม่ได้ |
| onConfirm | () => void | — | เรียกเมื่อกดปุ่มยืนยัน (กล่องไม่ปิดเอง — ปิดผ่าน onOpenChange หลังงานเสร็จ) |
ข้อควรรู้
- ปิดหลังงานเสร็จเอง: onConfirm แล้วรอ (เช่น await fetch) จากนั้น setOpen(false)
- ระหว่าง loading ปิดทั้งสองปุ่มกันกดซ้ำซ้อน
ซอร์สโค้ด
components/ui/confirm-dialog.tsx
"use client"import * as React from "react"import { LoaderIcon } from "lucide-react"import { cn } from "cn"import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle,} from "@/components/ui/alert-dialog"// กล่องยืนยันบน AlertDialog — controlled ผ่าน open/onOpenChange// ขณะ loading ปุ่มทั้งคู่ถูกปิด ฝั่งผู้ใช้ปิดเองหลังงานเสร็จfunction ConfirmDialog({ className, open, defaultOpen, onOpenChange, title, description, confirmLabel = "ยืนยัน", cancelLabel = "ยกเลิก", variant = "default", loading = false, onConfirm,}: { className?: string open?: boolean defaultOpen?: boolean onOpenChange?: (open: boolean) => void title: React.ReactNode description?: React.ReactNode confirmLabel?: string cancelLabel?: string /** destructive = หัวเรื่องและปุ่มยืนยันเป็นสีแดง สำหรับการลบ */ variant?: "default" | "destructive" /** สถานะกำลังทำงานของปุ่มยืนยัน */ loading?: boolean onConfirm?: () => void}) { return ( <AlertDialog open={open} defaultOpen={defaultOpen} onOpenChange={onOpenChange} > <AlertDialogContent data-slot="confirm-dialog" className={cn(className)}> <AlertDialogHeader> <AlertDialogTitle className={variant === "destructive" ? "text-destructive" : undefined} > {title} </AlertDialogTitle> {description ? ( <AlertDialogDescription>{description}</AlertDialogDescription> ) : null} </AlertDialogHeader> <AlertDialogFooter> <AlertDialogCancel disabled={loading}> {cancelLabel} </AlertDialogCancel> <AlertDialogAction variant={variant === "destructive" ? "destructive" : "default"} disabled={loading} onClick={() => onConfirm?.()} > {loading ? ( <LoaderIcon aria-hidden="true" className="animate-spin" /> ) : null} {confirmLabel} </AlertDialogAction> </AlertDialogFooter> </AlertDialogContent> </AlertDialog> )}export { ConfirmDialog }