Files
chorus-services-website/utils/animations.ts
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

644 lines
11 KiB
TypeScript

import { Variants } from 'framer-motion';
/**
* Common animation variants for Framer Motion
* Provides consistent animations across the application
*/
export const fadeInUp: Variants = {
hidden: {
opacity: 0,
y: 30,
},
visible: {
opacity: 1,
y: 0,
transition: {
duration: 0.6,
ease: 'easeOut',
},
},
};
export const fadeInDown: Variants = {
hidden: {
opacity: 0,
y: -30,
},
visible: {
opacity: 1,
y: 0,
transition: {
duration: 0.6,
ease: 'easeOut',
},
},
};
export const fadeInLeft: Variants = {
hidden: {
opacity: 0,
x: -30,
},
visible: {
opacity: 1,
x: 0,
transition: {
duration: 0.6,
ease: 'easeOut',
},
},
};
export const fadeInRight: Variants = {
hidden: {
opacity: 0,
x: 30,
},
visible: {
opacity: 1,
x: 0,
transition: {
duration: 0.6,
ease: 'easeOut',
},
},
};
export const fadeIn: Variants = {
hidden: {
opacity: 0,
},
visible: {
opacity: 1,
transition: {
duration: 0.6,
ease: 'easeOut',
},
},
};
export const scaleIn: Variants = {
hidden: {
opacity: 0,
scale: 0.8,
},
visible: {
opacity: 1,
scale: 1,
transition: {
duration: 0.6,
ease: 'easeOut',
},
},
};
export const slideInUp: Variants = {
hidden: {
y: '100%',
opacity: 0,
},
visible: {
y: '0%',
opacity: 1,
transition: {
duration: 0.6,
ease: 'easeOut',
},
},
};
export const slideInDown: Variants = {
hidden: {
y: '-100%',
opacity: 0,
},
visible: {
y: '0%',
opacity: 1,
transition: {
duration: 0.6,
ease: 'easeOut',
},
},
};
export const staggerContainer: Variants = {
hidden: {},
visible: {
transition: {
staggerChildren: 0.1,
delayChildren: 0.1,
},
},
};
export const staggerFast: Variants = {
hidden: {},
visible: {
transition: {
staggerChildren: 0.05,
},
},
};
export const staggerSlow: Variants = {
hidden: {},
visible: {
transition: {
staggerChildren: 0.2,
},
},
};
// Hover animations
export const hoverScale: Variants = {
hover: {
scale: 1.05,
transition: {
duration: 0.2,
ease: 'easeInOut',
},
},
};
export const hoverLift: Variants = {
hover: {
y: -5,
transition: {
duration: 0.2,
ease: 'easeInOut',
},
},
};
export const hoverGlow: Variants = {
hover: {
boxShadow: '0 0 30px rgba(0, 122, 255, 0.3)',
transition: {
duration: 0.3,
ease: 'easeInOut',
},
},
};
// Specialized animations for CHORUS components
export const orchestrationFlow: Variants = {
hidden: {
pathLength: 0,
opacity: 0,
},
visible: {
pathLength: 1,
opacity: 1,
transition: {
pathLength: {
duration: 2,
ease: 'easeInOut',
},
opacity: {
duration: 0.3,
},
},
},
};
export const dataFlow: Variants = {
hidden: {
opacity: 0,
scale: 0,
},
visible: (i: number) => ({
opacity: 1,
scale: 1,
transition: {
delay: i * 0.2,
duration: 0.5,
ease: 'easeOut',
},
}),
};
export const pulseAnimation: Variants = {
pulse: {
scale: [1, 1.1, 1],
opacity: [1, 0.8, 1],
transition: {
duration: 2,
repeat: Infinity,
ease: 'easeInOut',
},
},
};
export const rotateAnimation: Variants = {
rotate: {
rotate: 360,
transition: {
duration: 2,
repeat: Infinity,
ease: 'linear',
},
},
};
// Page transition animations
export const pageTransition: Variants = {
initial: {
opacity: 0,
y: 20,
},
animate: {
opacity: 1,
y: 0,
transition: {
duration: 0.4,
ease: 'easeOut',
},
},
exit: {
opacity: 0,
y: -20,
transition: {
duration: 0.3,
ease: 'easeIn',
},
},
};
// Modal animations
export const modalBackdrop: Variants = {
hidden: {
opacity: 0,
},
visible: {
opacity: 1,
transition: {
duration: 0.3,
},
},
};
export const modalContent: Variants = {
hidden: {
opacity: 0,
scale: 0.8,
y: 50,
},
visible: {
opacity: 1,
scale: 1,
y: 0,
transition: {
duration: 0.4,
ease: 'easeOut',
},
},
};
// Loading animations
export const spinnerAnimation: Variants = {
spin: {
rotate: 360,
transition: {
duration: 1,
repeat: Infinity,
ease: 'linear',
},
},
};
export const dotsLoading: Variants = {
loading: {
scale: [1, 1.2, 1],
opacity: [1, 0.6, 1],
transition: {
duration: 0.8,
repeat: Infinity,
ease: 'easeInOut',
},
},
};
// Apple-inspired easing curves
export const appleEasing = [0.21, 1.11, 0.81, 0.99]; // Apple's signature cubic-bezier
export const appleSpring = {
type: 'spring',
stiffness: 400,
damping: 30,
mass: 1,
};
// Advanced parallax animations
export const parallaxSlow: Variants = {
hidden: { y: 0, opacity: 0 },
visible: {
y: 0,
opacity: 1,
transition: {
duration: 1,
ease: appleEasing,
},
},
};
export const parallaxMedium: Variants = {
hidden: { y: 0, opacity: 0 },
visible: {
y: 0,
opacity: 1,
transition: {
duration: 0.8,
ease: appleEasing,
},
},
};
export const parallaxFast: Variants = {
hidden: { y: 0, opacity: 0 },
visible: {
y: 0,
opacity: 1,
transition: {
duration: 0.6,
ease: appleEasing,
},
},
};
// Gradient text animation
export const gradientTextAnimation: Variants = {
initial: {
backgroundPosition: '0% 50%',
},
animate: {
backgroundPosition: ['0% 50%', '100% 50%', '0% 50%'],
transition: {
duration: 5,
repeat: Infinity,
ease: 'easeInOut',
},
},
};
// Advanced button hover states
export const appleButtonHover: Variants = {
initial: {
scale: 1,
boxShadow: '0 4px 14px 0 rgba(0, 122, 255, 0.25)',
},
hover: {
scale: 1.05,
boxShadow: '0 8px 25px 0 rgba(0, 122, 255, 0.4)',
transition: {
duration: 0.2,
ease: 'easeOut',
},
},
tap: {
scale: 0.98,
transition: {
duration: 0.1,
},
},
};
// Hero entrance animations
export const heroEntrance: Variants = {
hidden: {
opacity: 0,
y: 60,
scale: 0.95,
},
visible: {
opacity: 1,
y: 0,
scale: 1,
transition: {
duration: 0.8,
ease: appleEasing,
},
},
};
// Staggered hero container
export const heroStaggerContainer: Variants = {
hidden: {},
visible: {
transition: {
staggerChildren: 0.2,
delayChildren: 0.3,
},
},
};
// Floating elements animation
export const floatingAnimation: Variants = {
initial: {
y: 0,
rotate: 0,
},
animate: {
y: [-10, 10, -10],
rotate: [-2, 2, -2],
transition: {
duration: 6,
repeat: Infinity,
ease: 'easeInOut',
},
},
};
// Geometric shape animations
export const geometricShapeAnimation: Variants = {
initial: {
scale: 1,
opacity: 0.2,
rotate: 0,
},
animate: {
scale: [1, 1.5, 1],
opacity: [0.2, 0.8, 0.2],
rotate: [0, 360],
transition: {
duration: 8,
repeat: Infinity,
ease: 'easeInOut',
},
},
};
// Interactive hover glow effect
export const interactiveGlow: Variants = {
initial: {
boxShadow: '0 0 0 rgba(0, 122, 255, 0)',
},
hover: {
boxShadow: '0 0 30px rgba(0, 122, 255, 0.3)',
transition: {
duration: 0.3,
ease: 'easeOut',
},
},
};
// Advanced scroll-triggered animations
export const scrollReveal: Variants = {
hidden: {
opacity: 0,
y: 75,
scale: 0.9,
},
visible: {
opacity: 1,
y: 0,
scale: 1,
transition: {
duration: 0.8,
ease: appleEasing,
},
},
};
// Performance-optimized fade variants
export const performantFade: Variants = {
hidden: {
opacity: 0,
transform: 'translateY(20px) translateZ(0)',
},
visible: {
opacity: 1,
transform: 'translateY(0px) translateZ(0)',
transition: {
duration: 0.6,
ease: appleEasing,
},
},
};
// Utility functions for animations
export const createStaggeredAnimation = (
baseAnimation: Variants,
staggerDelay: number = 0.1
): Variants => ({
...baseAnimation,
visible: {
...baseAnimation.visible,
transition: {
...baseAnimation.visible?.transition,
staggerChildren: staggerDelay,
},
},
});
export const createDelayedAnimation = (
baseAnimation: Variants,
delay: number
): Variants => ({
...baseAnimation,
visible: {
...baseAnimation.visible,
transition: {
...baseAnimation.visible?.transition,
delay,
},
},
});
export const createCustomEasing = (
baseAnimation: Variants,
ease: string | number[]
): Variants => ({
...baseAnimation,
visible: {
...baseAnimation.visible,
transition: {
...baseAnimation.visible?.transition,
ease,
},
},
});
// Parallax utility function
export const createParallaxAnimation = (
speed: number,
direction: 'up' | 'down' | 'left' | 'right' = 'up'
) => {
const axis = direction === 'left' || direction === 'right' ? 'x' : 'y';
const multiplier = direction === 'down' || direction === 'right' ? 1 : -1;
return {
[axis]: `${speed * multiplier * 100}px`,
};
};
// Scroll-based animation utility
export const createScrollAnimation = (
element: React.RefObject<HTMLElement>,
options: {
start?: number;
end?: number;
property: string;
from: any;
to: any;
}
) => {
// This would be used with useScroll and useTransform hooks
return {
scrollTrigger: {
trigger: element.current,
start: options.start || 0,
end: options.end || 1000,
scrub: true,
},
[options.property]: [options.from, options.to],
};
};
// Reduced motion variants for accessibility
export const createReducedMotionVariant = (baseVariant: Variants): Variants => {
const prefersReducedMotion = typeof window !== 'undefined' &&
window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (prefersReducedMotion) {
return {
...baseVariant,
visible: {
...baseVariant.visible,
transition: {
duration: 0.01, // Nearly instant
},
},
};
}
return baseVariant;
};
// Apple-style elastic animation
export const elasticAnimation = {
type: 'spring',
stiffness: 500,
damping: 25,
mass: 0.8,
};
// Magnetic effect for interactive elements
export const magneticEffect = {
hover: {
scale: 1.1,
transition: {
type: 'spring',
stiffness: 400,
damping: 10,
},
},
tap: {
scale: 0.95,
transition: {
type: 'spring',
stiffness: 600,
damping: 15,
},
},
};