mirror of
https://github.com/luckfox-eng29/kvm.git
synced 2026-01-19 09:52:32 +01:00
Release 202412292127
This commit is contained in:
87
ui/src/notifications.tsx
Normal file
87
ui/src/notifications.tsx
Normal file
@@ -0,0 +1,87 @@
|
||||
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,
|
||||
});
|
||||
Reference in New Issue
Block a user