kvm/ui/src/notifications.tsx

88 lines
2.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import toast, { Toast, Toaster, useToasterStore } from "react-hot-toast";
import React, { useEffect } from "react";
import Card from "@/components/Card";
import { CheckCircleIcon, XCircleIcon } from "@heroicons/react/20/solid";
interface NotificationOptions {
duration?: number;
// Add other options as needed
}
const ToastContent = ({
icon,
message,
t,
}: {
icon: React.ReactNode;
message: string;
t: Toast;
}) => (
<Card
className={`${
t.visible ? "animate-enter" : "animate-leave"
} pointer-events-auto z-30 w-full max-w-sm !shadow-xl`}
>
<div className="flex items-center gap-x-2 p-2.5 px-2">
{icon}
<p className="text-[14px] font-medium text-gray-900 dark:text-gray-100">{message}</p>
</div>
</Card>
);
const notifications = {
success: (message: string, options?: NotificationOptions) => {
return toast.custom(
t => (
<ToastContent
icon={<CheckCircleIcon className="w-5 h-5 text-green-500 dark:text-green-400" />}
message={message}
t={t}
/>
),
{ duration: 2000, ...options },
);
},
error: (message: string, options?: NotificationOptions) => {
return toast.custom(
t => (
<ToastContent
icon={<XCircleIcon className="w-5 h-5 text-red-500 dark:text-red-400" />}
message={message}
t={t}
/>
),
{ duration: 2000, ...options },
);
},
};
function useMaxToasts(max: number) {
const { toasts } = useToasterStore();
useEffect(() => {
toasts
.filter(t => t.visible) // Only consider visible toasts
.filter((_, i) => i >= max) // Is toast index over limit?
.forEach(t => toast.dismiss(t.id)); // Dismiss Use toast.remove(t.id) for no exit animation
}, [toasts, max]);
}
export function Notifications({
max = 10,
...props
}: React.ComponentProps<typeof Toaster> & {
max?: number;
}) {
useMaxToasts(max);
return <Toaster {...props} />;
}
// eslint-disable-next-line react-refresh/only-export-components
export default Object.assign(Notifications, {
success: notifications.success,
error: notifications.error,
});