109 lines
3.2 KiB
TypeScript
109 lines
3.2 KiB
TypeScript
"use client";
|
|
|
|
import Link from "next/link";
|
|
import { motion } from "framer-motion";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
interface CyberButtonProps {
|
|
href?: string;
|
|
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
children: React.ReactNode;
|
|
className?: string;
|
|
variant?: "primary" | "secondary";
|
|
disabled?: boolean;
|
|
type?: "button" | "submit" | "reset";
|
|
}
|
|
|
|
export function CyberButton({
|
|
href,
|
|
onClick,
|
|
children,
|
|
className,
|
|
variant = "primary",
|
|
disabled = false,
|
|
type = "button",
|
|
}: CyberButtonProps) {
|
|
const isPrimary = variant === "primary";
|
|
|
|
const content = (
|
|
<motion.div
|
|
whileHover={!disabled ? { scale: 1.02 } : {}}
|
|
whileTap={!disabled ? { scale: 0.98 } : {}}
|
|
className={cn(
|
|
"relative z-10 flex items-center justify-center px-6 py-3 overflow-hidden transition-all duration-300 border rounded-xl font-mono", // Уменьшил padding
|
|
!disabled && [
|
|
isPrimary
|
|
? "bg-[#8B3DFF] border-[#8B3DFF] text-white shadow-lg shadow-purple-500/20 dark:bg-[radial-gradient(circle_at_center,_rgba(139,61,255,0.4)_0%,_rgba(139,61,255,0.1)_100%)] dark:border-[#8B3DFF]/50 dark:shadow-[0_0_25px_rgba(139,61,255,0.3)]"
|
|
: "text-[#0284c7] dark:text-[#00E5F2] border-[#0284c7]/40 dark:border-[#00E5F2]/40 backdrop-blur-md bg-slate-900/5 dark:bg-[#00E5F2]/5",
|
|
],
|
|
disabled && "cursor-not-allowed opacity-50 border-dashed",
|
|
className,
|
|
)}
|
|
>
|
|
{/* Энергетический блик */}
|
|
{!disabled && (
|
|
<div className="absolute inset-0 w-full h-full -translate-x-full group-hover:animate-scan pointer-events-none bg-gradient-to-r from-transparent via-white/10 to-transparent" />
|
|
)}
|
|
|
|
{/* Улучшенные скобки-маркеры */}
|
|
<div className="flex items-center gap-3">
|
|
<span
|
|
className={cn(
|
|
"text-[10px] font-bold transition-transform group-hover:-translate-x-0.5",
|
|
isPrimary ? "text-white/50" : "text-secondary/50",
|
|
)}
|
|
>
|
|
</
|
|
</span>
|
|
|
|
<span className="relative z-20 font-black uppercase tracking-wider text-xs flex items-center gap-2">
|
|
{children}
|
|
</span>
|
|
|
|
<span
|
|
className={cn(
|
|
"text-[10px] font-bold transition-transform group-hover:translate-x-0.5",
|
|
isPrimary ? "text-white/50" : "text-secondary/50",
|
|
)}
|
|
>
|
|
/>
|
|
</span>
|
|
</div>
|
|
</motion.div>
|
|
);
|
|
|
|
const glowEffect = !disabled && (
|
|
<div
|
|
className={cn(
|
|
"absolute inset-0 blur-xl opacity-0 group-hover:opacity-30 transition-opacity duration-500 -z-10",
|
|
isPrimary ? "bg-[#8B3DFF]" : "bg-[#00E5F2]",
|
|
)}
|
|
/>
|
|
);
|
|
|
|
if (href && !disabled) {
|
|
return (
|
|
<Link
|
|
href={href}
|
|
onClick={(e) => onClick?.(e as any)}
|
|
className="group relative inline-block"
|
|
>
|
|
{content}
|
|
{glowEffect}
|
|
</Link>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<button
|
|
type={type}
|
|
disabled={disabled}
|
|
onClick={onClick}
|
|
className="group relative inline-block bg-transparent border-none p-0 outline-none cursor-pointer"
|
|
>
|
|
{content}
|
|
{glowEffect}
|
|
</button>
|
|
);
|
|
}
|