Files
chorus-services-website/components/ui/Button.tsx
anthonyrawlins f343f89d24 Initial commit: CHORUS Services marketing website
Complete Next.js website with Docker containerization:
- Next.js 14 with TypeScript and Tailwind CSS
- Responsive design with modern UI components
- Hero section, features showcase, testimonials
- FAQ section with comprehensive content
- Contact forms and newsletter signup
- Docker production build with Nginx
- Health checks and monitoring support
- SEO optimization and performance tuning

Ready for integration as git submodule in main CHORUS project.

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-01 22:45:06 +10:00

100 lines
2.8 KiB
TypeScript

'use client';
import React from 'react';
import { Button as AntButton, ButtonProps as AntButtonProps } from 'antd';
import { motion, MotionProps } from 'framer-motion';
import { cn } from '@/utils/cn';
// Extend Ant Design ButtonProps with custom variants
interface CustomButtonProps {
variant?: 'primary' | 'secondary' | 'outline' | 'ghost' | 'gradient';
fullWidth?: boolean;
animated?: boolean;
}
type ButtonProps = AntButtonProps & CustomButtonProps & Partial<MotionProps>;
const MotionButton = motion(AntButton);
export const Button: React.FC<ButtonProps> = ({
variant = 'primary',
fullWidth = false,
animated = true,
className,
children,
...props
}) => {
const getVariantClasses = () => {
switch (variant) {
case 'primary':
return 'bg-chorus-blue hover:bg-blue-600 border-chorus-blue hover:border-blue-600 text-white shadow-lg hover:shadow-xl';
case 'secondary':
return 'bg-chorus-green hover:bg-green-600 border-chorus-green hover:border-green-600 text-white shadow-lg hover:shadow-xl';
case 'outline':
return 'bg-transparent border-2 border-chorus-blue text-chorus-blue hover:bg-chorus-blue hover:text-white';
case 'ghost':
return 'bg-transparent border-transparent text-white hover:bg-white/10 hover:border-white/20';
case 'gradient':
return 'bg-gradient-chorus border-transparent text-white shadow-lg hover:shadow-xl';
default:
return '';
}
};
const buttonClasses = cn(
'font-semibold transition-all duration-200 border-0 rounded-lg',
'focus:ring-2 focus:ring-chorus-blue focus:ring-opacity-50 focus:outline-none',
getVariantClasses(),
fullWidth && 'w-full',
className
);
const animationProps = animated
? {
whileHover: { scale: 1.02 },
whileTap: { scale: 0.98 },
transition: { duration: 0.2 },
}
: {};
if (animated) {
return (
<MotionButton
className={buttonClasses}
{...animationProps}
{...props}
>
{children}
</MotionButton>
);
}
return (
<AntButton className={buttonClasses} {...props}>
{children}
</AntButton>
);
};
// Specific button variants for common use cases
export const PrimaryButton: React.FC<Omit<ButtonProps, 'variant'>> = (props) => (
<Button variant="primary" {...props} />
);
export const SecondaryButton: React.FC<Omit<ButtonProps, 'variant'>> = (props) => (
<Button variant="secondary" {...props} />
);
export const OutlineButton: React.FC<Omit<ButtonProps, 'variant'>> = (props) => (
<Button variant="outline" {...props} />
);
export const GhostButton: React.FC<Omit<ButtonProps, 'variant'>> = (props) => (
<Button variant="ghost" {...props} />
);
export const GradientButton: React.FC<Omit<ButtonProps, 'variant'>> = (props) => (
<Button variant="gradient" {...props} />
);
export default Button;