Triviaverse / src /components /ui /Button.tsx
Simeon Garratt
feat: upgrade GlassCard to use glass-card CSS class and add glow prop, add glow classes to Button variants
fe87a10
Raw
History Blame Contribute Delete
2.08 kB
"use client";
import { motion } from "framer-motion";
type ButtonVariant = "primary" | "secondary" | "ghost" | "danger";
type ButtonSize = "sm" | "md" | "lg";
/**
* Shared animated button component with four visual variants and three sizes.
*
* Variants:
* - primary: magenta gradient
* - secondary: gold gradient
* - ghost: transparent with white border
* - danger: red gradient
*
* Sizes: sm | md | lg
*/
interface ButtonProps {
children: React.ReactNode;
variant?: ButtonVariant;
size?: ButtonSize;
className?: string;
disabled?: boolean;
type?: "button" | "submit" | "reset";
onClick?: () => void;
}
const variantStyles: Record<ButtonVariant, string> = {
primary:
"bg-gradient-to-r from-magenta to-purple-600 text-white shadow-lg shadow-magenta/25 hover:shadow-magenta/40 glow-magenta border border-white/10",
secondary:
"bg-gradient-to-r from-gold to-amber-400 text-navy font-semibold shadow-lg shadow-gold/25 hover:shadow-gold/40 glow-gold border border-white/10",
ghost:
"border border-white/20 text-white bg-transparent hover:bg-white/5 hover:border-white/40",
danger:
"bg-gradient-to-r from-red-600 to-rose-500 text-white shadow-lg shadow-red-500/25 hover:shadow-red-500/40",
};
const sizeStyles: Record<ButtonSize, string> = {
sm: "px-4 py-2 text-sm rounded-xl",
md: "px-6 py-3 text-base rounded-xl",
lg: "px-8 py-4 text-lg rounded-2xl",
};
export function Button({
children,
variant = "primary",
size = "md",
className = "",
disabled = false,
type = "button",
onClick,
}: ButtonProps) {
return (
<motion.button
type={type}
disabled={disabled}
onClick={onClick}
className={`
inline-flex items-center justify-center font-medium transition-colors
disabled:opacity-50 disabled:cursor-not-allowed
${variantStyles[variant]}
${sizeStyles[size]}
${className}
`}
whileHover={disabled ? undefined : { scale: 1.03 }}
whileTap={disabled ? undefined : { scale: 0.97 }}
>
{children}
</motion.button>
);
}