52
components/Button.tsx
Normal file
52
components/Button.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
import React from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
variant?: 'primary' | 'secondary' | 'danger' | 'ghost';
|
||||
roleTheme?: 'mom' | 'dad' | 'neutral';
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
export const Button: React.FC<ButtonProps> = ({
|
||||
children,
|
||||
variant = 'primary',
|
||||
roleTheme = 'neutral',
|
||||
isLoading,
|
||||
className = '',
|
||||
...props
|
||||
}) => {
|
||||
|
||||
let baseStyles = "px-6 py-3 rounded-2xl font-bold transition-all duration-200 flex items-center justify-center gap-2 outline-none focus:ring-4 disabled:opacity-50 disabled:cursor-not-allowed";
|
||||
|
||||
const getThemeColors = () => {
|
||||
if (variant === 'ghost') return "bg-transparent hover:bg-gray-100 text-gray-600 focus:ring-gray-200";
|
||||
if (variant === 'danger') return "bg-red-100 text-red-600 hover:bg-red-200 focus:ring-red-100";
|
||||
if (variant === 'secondary') return "bg-white text-gray-700 border-2 border-gray-100 hover:border-gray-200 focus:ring-gray-100";
|
||||
|
||||
switch (roleTheme) {
|
||||
case 'mom':
|
||||
return "bg-mom-primary text-white hover:bg-pink-500 shadow-lg shadow-pink-200 focus:ring-pink-200";
|
||||
case 'dad':
|
||||
return "bg-dad-primary text-white hover:bg-blue-500 shadow-lg shadow-blue-200 focus:ring-blue-200";
|
||||
default:
|
||||
return "bg-gray-800 text-white hover:bg-gray-900 shadow-lg shadow-gray-300 focus:ring-gray-200";
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<motion.button
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
className={`${baseStyles} ${getThemeColors()} ${className}`}
|
||||
disabled={isLoading || props.disabled}
|
||||
{...props}
|
||||
>
|
||||
{isLoading ? (
|
||||
<svg className="animate-spin h-5 w-5" viewBox="0 0 24 24">
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" />
|
||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
|
||||
</svg>
|
||||
) : children}
|
||||
</motion.button>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user