66 lines
2.2 KiB
TypeScript
66 lines
2.2 KiB
TypeScript
"use client";
|
|
import React from "react";
|
|
import { motion } from "motion/react";
|
|
import { toPersian, cn } from "../lib/utils";
|
|
|
|
interface HeaderButtonProps {
|
|
onClick?: () => void;
|
|
children: React.ReactNode;
|
|
variant?: "primary" | "secondary" | "outline" | "ghost";
|
|
className?: string;
|
|
badge?: number;
|
|
icon?: React.ReactNode;
|
|
layout?: "row" | "col";
|
|
}
|
|
|
|
export default function HeaderButton({
|
|
onClick,
|
|
children,
|
|
variant = "primary",
|
|
className = "",
|
|
badge,
|
|
icon,
|
|
layout = "col"
|
|
}: HeaderButtonProps) {
|
|
const baseStyles = "relative flex items-center justify-center rounded-2xl transition-all duration-300 font-vazir select-none cursor-pointer overflow-visible focus-visible:ring-4 focus-visible:ring-canina-blue/30 focus-visible:outline-none";
|
|
|
|
const layouts = {
|
|
col: "flex-col",
|
|
row: "flex-row gap-2"
|
|
};
|
|
|
|
const variants = {
|
|
primary: "bg-canina-blue text-white hover:bg-medical-gray-900 shadow-lg shadow-canina-blue/20",
|
|
secondary: "bg-medical-gray-50 text-medical-gray-600 hover:bg-medical-gray-100",
|
|
outline: "border-2 border-medical-gray-100 text-medical-gray-700 hover:border-canina-blue hover:text-canina-blue",
|
|
ghost: "text-medical-gray-600 hover:bg-medical-gray-50 hover:text-canina-blue"
|
|
};
|
|
|
|
const [mounted, setMounted] = React.useState(false);
|
|
React.useEffect(() => {
|
|
Promise.resolve().then(() => setMounted(true));
|
|
}, []);
|
|
|
|
return (
|
|
<motion.button
|
|
whileHover={{ y: -2 }}
|
|
whileTap={{ scale: 0.95 }}
|
|
onClick={onClick}
|
|
className={cn(baseStyles, layouts[layout], variants[variant], className)}
|
|
>
|
|
{icon && <div className={cn(layout === "col" ? "mb-0.5" : "flex-shrink-0 flex items-center")}>{icon}</div>}
|
|
<div className="whitespace-nowrap flex items-center">{children}</div>
|
|
|
|
{mounted && badge !== undefined && badge > 0 && (
|
|
<motion.div
|
|
initial={{ scale: 0 }}
|
|
animate={{ scale: 1 }}
|
|
className="absolute -top-1 -left-1 w-5 h-5 bg-red-500 text-white rounded-full border-2 border-white text-[8px] font-black flex items-center justify-center font-vazir"
|
|
>
|
|
{toPersian(badge.toString())}
|
|
</motion.div>
|
|
)}
|
|
</motion.button>
|
|
);
|
|
}
|