You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
2.4 KiB
89 lines
2.4 KiB
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { IoClose } from "react-icons/io5";
|
|
|
|
type ErrorToastProps = {
|
|
title?: string;
|
|
message: string;
|
|
onClose: () => void;
|
|
duration?: number;
|
|
variant?: "error" | "success" | "warning" | "info";
|
|
};
|
|
|
|
export default function ErrorToast({
|
|
title,
|
|
message,
|
|
onClose,
|
|
duration = 4000,
|
|
variant = "error",
|
|
}: ErrorToastProps) {
|
|
const [isVisible, setIsVisible] = useState(true);
|
|
|
|
useEffect(() => {
|
|
const timer = setTimeout(() => {
|
|
setIsVisible(false);
|
|
setTimeout(onClose, 300); // Wait for fade-out animation to complete
|
|
}, duration);
|
|
|
|
return () => clearTimeout(timer);
|
|
}, [duration, onClose]);
|
|
|
|
const handleClose = () => {
|
|
setIsVisible(false);
|
|
setTimeout(onClose, 300);
|
|
};
|
|
|
|
const getBorderColor = () => {
|
|
switch (variant) {
|
|
case "success":
|
|
return "border-t-[#10B981]";
|
|
case "warning":
|
|
return "border-t-[#F59E0B]";
|
|
case "info":
|
|
return "border-t-[#3B82F6]";
|
|
case "error":
|
|
default:
|
|
return "border-t-[#F0445B]";
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div
|
|
className={[
|
|
"fixed top-3.5 left-1/2 z-50 flex w-[calc(100%-32px)] max-w-[360px] -translate-x-1/2 items-start justify-between gap-3 rounded-[16px] bg-[#141414]/95 p-3.5 px-4 text-white shadow-[0_10px_30px_rgba(0,0,0,0.35)] backdrop-blur-md border border-white/5 border-t-[2.5px] transition-all duration-300 ease-out",
|
|
getBorderColor(),
|
|
isVisible
|
|
? "translate-y-0 opacity-100 scale-100"
|
|
: "-translate-y-4 opacity-0 scale-95",
|
|
].join(" ")}
|
|
role="alert"
|
|
>
|
|
<div className="flex flex-1 flex-col text-start min-w-0">
|
|
{title && (
|
|
<span className="text-[15px] font-bold text-white leading-tight truncate mb-1">
|
|
{title}
|
|
</span>
|
|
)}
|
|
<span
|
|
className={[
|
|
"text-[#E0E0E0] leading-snug break-words",
|
|
title ? "text-[13px] text-white/80" : "text-[14px] font-medium text-white",
|
|
].join(" ")}
|
|
>
|
|
{message}
|
|
</span>
|
|
</div>
|
|
|
|
<button
|
|
type="button"
|
|
onClick={handleClose}
|
|
className="flex size-7 shrink-0 items-center justify-center rounded-lg text-white/70 hover:text-white transition-colors cursor-pointer self-start -me-1 -mt-0.5"
|
|
aria-label="Close toast"
|
|
>
|
|
<IoClose className="size-5" />
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|
|
|