first commit
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
"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,
|
||||
}
|
||||
Reference in New Issue
Block a user