CVE-ReRanker / frontend /components /ShinyButton.tsx
ManglamX's picture
UI Redesign with BorderGlow & Lucide Icons, Workflow Fixes for GitHub Actions LFS
8d095ff
Raw
History Blame Contribute Delete
2.44 kB
"use client";
import { motion, useMotionValue, useTransform, MotionValue } from "framer-motion";
import { ReactNode } from "react";
interface ShinyButtonProps {
children: ReactNode;
onClick?: () => void;
disabled?: boolean;
type?: "button" | "submit" | "reset";
variant?: "primary" | "secondary" | "danger";
className?: string;
style?: React.CSSProperties;
}
function useShine(x: MotionValue<number>, y: MotionValue<number>) {
const background = useTransform(
[x, y],
([lx, ly]) =>
`radial-gradient(circle at ${(lx as number) * 100}% ${(ly as number) * 100}%, rgba(255,255,255,0.18) 0%, transparent 60%)`
);
return background;
}
export default function ShinyButton({
children,
onClick,
disabled,
type = "button",
variant = "primary",
className = "",
style,
}: ShinyButtonProps) {
const x = useMotionValue(0.5);
const y = useMotionValue(0.5);
const shine = useShine(x, y);
const handleMouseMove = (e: React.MouseEvent<HTMLButtonElement>) => {
const rect = e.currentTarget.getBoundingClientRect();
x.set((e.clientX - rect.left) / rect.width);
y.set((e.clientY - rect.top) / rect.height);
};
const handleMouseLeave = () => { x.set(0.5); y.set(0.5); };
const base: React.CSSProperties =
variant === "primary"
? { background: "linear-gradient(135deg, #58a6ff, #39d0d8)", color: "#0d1117" }
: variant === "danger"
? { background: "linear-gradient(135deg, #f85149, #ff6b6b)", color: "#fff" }
: { background: "rgba(255,255,255,0.06)", border: "1px solid rgba(255,255,255,0.12)", color: "#e6edf3" };
return (
<motion.button
type={type}
onClick={onClick}
disabled={disabled}
className={`shiny-btn ${className}`}
style={{ ...base, position: "relative", overflow: "hidden", ...style }}
onMouseMove={handleMouseMove}
onMouseLeave={handleMouseLeave}
whileHover={disabled ? {} : { scale: 1.03, y: -1 }}
whileTap={disabled ? {} : { scale: 0.97 }}
transition={{ type: "spring", stiffness: 400, damping: 25 }}
>
<motion.span
style={{
position: "absolute",
inset: 0,
background: shine,
pointerEvents: "none",
borderRadius: "inherit",
}}
/>
<span style={{ position: "relative", zIndex: 1, display: "flex", alignItems: "center", gap: 8 }}>
{children}
</span>
</motion.button>
);
}