90 lines
2.7 KiB
TypeScript
90 lines
2.7 KiB
TypeScript
import Link from "next/link";
|
|
import { ReactNode } from "react";
|
|
|
|
interface ButtonProps {
|
|
href?: string;
|
|
onClick?: () => void;
|
|
children: ReactNode;
|
|
variant?: "primary" | "secondary" | "ghost" | "outline";
|
|
size?: "sm" | "md" | "lg";
|
|
className?: string;
|
|
external?: boolean;
|
|
type?: "button" | "submit";
|
|
disabled?: boolean;
|
|
}
|
|
|
|
export default function Button({
|
|
href,
|
|
onClick,
|
|
children,
|
|
variant = "primary",
|
|
size = "md",
|
|
className = "",
|
|
external = false,
|
|
type = "button",
|
|
disabled = false,
|
|
}: ButtonProps) {
|
|
const baseStyles =
|
|
"relative inline-flex items-center justify-center font-medium rounded-lg transition-all duration-300 overflow-hidden group";
|
|
|
|
const sizeStyles = {
|
|
sm: "px-4 py-2 text-sm",
|
|
md: "px-6 py-3 text-base",
|
|
lg: "px-8 py-4 text-lg",
|
|
};
|
|
|
|
const variantStyles = {
|
|
primary:
|
|
"bg-gradient-to-r from-red-600 to-red-500 text-white hover:from-red-700 hover:to-red-600 hover:shadow-lg hover:shadow-red-500/25 hover:-translate-y-0.5 active:translate-y-0",
|
|
secondary:
|
|
"bg-white text-zinc-900 border border-zinc-200 hover:border-zinc-300 hover:bg-zinc-50 hover:shadow-lg hover:-translate-y-0.5 active:translate-y-0",
|
|
ghost:
|
|
"text-red-600 hover:bg-red-50 hover:text-red-700",
|
|
outline:
|
|
"border-2 border-red-600 text-red-600 hover:bg-red-600 hover:text-white hover:shadow-lg hover:shadow-red-500/25 hover:-translate-y-0.5 active:translate-y-0",
|
|
};
|
|
|
|
const disabledStyles = "opacity-50 cursor-not-allowed hover:transform-none hover:shadow-none";
|
|
|
|
const combinedClassName = `${baseStyles} ${sizeStyles[size]} ${variantStyles[variant]} ${disabled ? disabledStyles : ""} ${className}`;
|
|
|
|
// Shimmer effect overlay
|
|
const shimmer = variant === "primary" && (
|
|
<span className="absolute inset-0 -translate-x-full group-hover:translate-x-full transition-transform duration-700 bg-gradient-to-r from-transparent via-white/20 to-transparent" />
|
|
);
|
|
|
|
if (href) {
|
|
if (external) {
|
|
return (
|
|
<a
|
|
href={href}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className={combinedClassName}
|
|
>
|
|
{shimmer}
|
|
<span className="relative z-10 flex items-center gap-2">{children}</span>
|
|
</a>
|
|
);
|
|
}
|
|
return (
|
|
<Link href={href} className={combinedClassName}>
|
|
{shimmer}
|
|
<span className="relative z-10 flex items-center gap-2">{children}</span>
|
|
</Link>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<button
|
|
type={type}
|
|
onClick={onClick}
|
|
disabled={disabled}
|
|
className={combinedClassName}
|
|
>
|
|
{shimmer}
|
|
<span className="relative z-10 flex items-center gap-2">{children}</span>
|
|
</button>
|
|
);
|
|
}
|