Files
ERP_Frontend/components/ui/alert-dialog.tsx
T
2026-07-08 11:08:24 +05:30

151 lines
4.5 KiB
TypeScript

"use client"
import * as React from "react"
import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog"
import { AlertTriangleIcon, InfoIcon, XCircleIcon, CheckCircle2Icon } from "lucide-react"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
function AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props) {
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />
}
function AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props) {
return <AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
}
function AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props) {
return <AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
}
function AlertDialogOverlay({
className,
...props
}: AlertDialogPrimitive.Backdrop.Props) {
return (
<AlertDialogPrimitive.Backdrop
data-slot="alert-dialog-overlay"
className={cn(
"fixed inset-0 isolate z-50 bg-black/20 backdrop-blur-xs duration-150 data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
className
)}
{...props}
/>
)
}
type AlertVariant = "info" | "warning" | "destructive" | "success"
const variantConfig: Record<
AlertVariant,
{ icon: React.ElementType; iconClass: string; ringClass: string }
> = {
info: {
icon: InfoIcon,
iconClass: "text-sky-600 bg-sky-50",
ringClass: "ring-sky-100",
},
warning: {
icon: AlertTriangleIcon,
iconClass: "text-amber-600 bg-amber-50",
ringClass: "ring-amber-100",
},
destructive: {
icon: XCircleIcon,
iconClass: "text-red-600 bg-red-50",
ringClass: "ring-red-100",
},
success: {
icon: CheckCircle2Icon,
iconClass: "text-emerald-600 bg-emerald-50",
ringClass: "ring-emerald-100",
},
}
interface AlertDialogContentProps extends AlertDialogPrimitive.Popup.Props {
variant?: AlertVariant
title: string
description?: string
confirmLabel?: string
cancelLabel?: string
onConfirm?: () => void
onCancel?: () => void
}
function AlertDialogContent({
className,
variant = "info",
title,
description,
confirmLabel = "Confirm",
cancelLabel = "Cancel",
onConfirm,
onCancel,
...props
}: AlertDialogContentProps) {
const { icon: Icon, iconClass, ringClass } = variantConfig[variant]
return (
<AlertDialogPortal>
<AlertDialogOverlay />
<AlertDialogPrimitive.Popup
data-slot="alert-dialog-content"
className={cn(
"fixed top-1/2 left-1/2 z-50 w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 rounded-2xl bg-white p-6 shadow-xl ring-1 duration-150 outline-none sm:max-w-sm",
"data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
ringClass,
className
)}
{...props}
>
<div className="flex flex-col items-center gap-4 text-center">
<div className={cn("flex size-14 items-center justify-center rounded-full", iconClass)}>
<Icon className="size-7" />
</div>
<div className="flex flex-col gap-1.5">
<AlertDialogPrimitive.Title className="text-base font-bold text-slate-900">
{title}
</AlertDialogPrimitive.Title>
{description && (
<AlertDialogPrimitive.Description className="text-sm text-slate-500">
{description}
</AlertDialogPrimitive.Description>
)}
</div>
<div className="mt-1 flex w-full flex-col-reverse gap-2 sm:flex-row sm:justify-center">
<AlertDialogPrimitive.Close
render={
<Button variant="outline" className="sm:min-w-24" onClick={onCancel} />
}
>
{cancelLabel}
</AlertDialogPrimitive.Close>
<AlertDialogPrimitive.Close
render={
<Button
variant={variant === "destructive" ? "destructive" : variant === "success" ? "success" : variant === "warning" ? "warning" : "info"}
className="sm:min-w-24"
onClick={onConfirm}
/>
}
>
{confirmLabel}
</AlertDialogPrimitive.Close>
</div>
</div>
</AlertDialogPrimitive.Popup>
</AlertDialogPortal>
)
}
export {
AlertDialog,
AlertDialogTrigger,
AlertDialogContent,
AlertDialogPortal,
AlertDialogOverlay,
}