This commit is contained in:
hamid zarghami
2025-08-25 09:19:13 +03:30
parent 418b45fde5
commit 6e1ebdf023
20 changed files with 736 additions and 10 deletions
+59
View File
@@ -0,0 +1,59 @@
'use client'
import { CloseCircle, InfoCircle, TickCircle } from 'iconsax-react';
import React, { useState, useEffect } from 'react';
interface Toast {
id: string;
message: string;
type?: 'success' | 'error' | 'info';
}
let addToast: (toast: Toast) => void;
const ToastContainer: React.FC = () => {
const [toasts, setToasts] = useState<Toast[]>([]);
// ثبت toast جدید
const showToast = (toast: Toast) => {
setToasts((prev) => [...prev, toast]);
// حذف خودکار بعد از ۳ ثانیه
setTimeout(() => {
setToasts((prev) => prev.filter((t) => t.id !== toast.id));
}, 3000);
};
// تخصیص تابع نمایش toast به متغیر سراسری
useEffect(() => {
addToast = showToast;
}, []);
return (
<div className="fixed top-4 text-sm right-0 left-0 mx-auto w-fit z-50 flex flex-col gap-2">
{toasts.map((toast) => (
<div
key={toast.id}
className={`px-4 flex items-center gap-2 backdrop-blur-2xl h-16 min-w-[300px] rounded-2xl shadow-md transition-transform ${toast.type === 'success'
? 'bg-white/70 text-black'
: toast.type === 'error'
? 'bg-white/70 text-black'
: 'bg-white/70 text-black'
}`}
>
{
toast.type === 'success' ? <TickCircle className='size-5' color='green' /> :
toast.type === 'error' ? <CloseCircle className='size-5' color='red' /> :
<InfoCircle className='size-5' color='blue' />
}
{toast.message}
</div>
))}
</div>
);
};
export const toast = (message: string, type: 'success' | 'error' | 'info' = 'info') => {
addToast({ id: Date.now().toString(), message, type });
};
export default ToastContainer;
+16 -1
View File
@@ -1,6 +1,7 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { ClipLoader } from "react-spinners"
import { cn } from "@/lib/utils"
@@ -40,10 +41,14 @@ function Button({
variant,
size,
asChild = false,
isLoading = false,
disabled,
children,
...props
}: React.ComponentProps<"button"> &
VariantProps<typeof buttonVariants> & {
asChild?: boolean
isLoading?: boolean
}) {
const Comp = asChild ? Slot : "button"
@@ -51,8 +56,18 @@ function Button({
<Comp
data-slot="button"
className={cn(buttonVariants({ variant, size, className }))}
disabled={disabled || isLoading}
{...props}
/>
>
{isLoading ? (
<>
<ClipLoader size={16} color="currentColor" />
<span>در حال بارگذاری...</span>
</>
) : (
children
)}
</Comp>
)
}