- Implemented ActivityFeed component to display real-time user activity including coding, music, and chat interactions. - Added GooFilter and BackgroundBlobs components for enhanced visual effects. - Updated layout to include new components and ensure proper stacking context. - Enhanced Tailwind CSS configuration with new color and font settings. - Created API route to mock activity data from n8n. - Refactored main page structure to streamline component rendering.
78 lines
2.6 KiB
TypeScript
78 lines
2.6 KiB
TypeScript
'use client';
|
|
|
|
import { motion, useMotionValue, useTransform, useSpring } from 'framer-motion';
|
|
import { useEffect, useState } from 'react';
|
|
|
|
export const BackgroundBlobs = () => {
|
|
const mouseX = useMotionValue(0);
|
|
const mouseY = useMotionValue(0);
|
|
|
|
const springConfig = { damping: 50, stiffness: 200 };
|
|
const springX = useSpring(mouseX, springConfig);
|
|
const springY = useSpring(mouseY, springConfig);
|
|
|
|
// Parallax offsets
|
|
const x1 = useTransform(springX, (value) => value / 20);
|
|
const y1 = useTransform(springY, (value) => value / 20);
|
|
|
|
const x2 = useTransform(springX, (value) => value / -15);
|
|
const y2 = useTransform(springY, (value) => value / -15);
|
|
|
|
const x3 = useTransform(springX, (value) => value / 10);
|
|
const y3 = useTransform(springY, (value) => value / 10);
|
|
|
|
useEffect(() => {
|
|
const handleMouseMove = (e: MouseEvent) => {
|
|
// Center the coordinate system
|
|
const { innerWidth, innerHeight } = window;
|
|
const x = e.clientX - innerWidth / 2;
|
|
const y = e.clientY - innerHeight / 2;
|
|
mouseX.set(x);
|
|
mouseY.set(y);
|
|
};
|
|
|
|
window.addEventListener('mousemove', handleMouseMove);
|
|
return () => window.removeEventListener('mousemove', handleMouseMove);
|
|
}, [mouseX, mouseY]);
|
|
|
|
// Prevent hydration mismatch
|
|
const [mounted, setMounted] = useState(false);
|
|
useEffect(() => {
|
|
setMounted(true);
|
|
}, []);
|
|
|
|
if (!mounted) return null;
|
|
|
|
return (
|
|
<div className="fixed inset-0 overflow-hidden pointer-events-none z-0 liquid-container">
|
|
<motion.div
|
|
className="absolute top-[-10%] left-[-10%] w-[40vw] h-[40vw] bg-liquid-mint/40 rounded-full blur-[80px] mix-blend-multiply opacity-70"
|
|
style={{ x: x1, y: y1 }}
|
|
animate={{
|
|
scale: [1, 1.2, 1],
|
|
rotate: [0, 90, 0],
|
|
}}
|
|
transition={{ duration: 25, repeat: Infinity, ease: "linear" }}
|
|
/>
|
|
<motion.div
|
|
className="absolute top-[20%] right-[-10%] w-[35vw] h-[35vw] bg-liquid-lavender/40 rounded-full blur-[80px] mix-blend-multiply opacity-70"
|
|
style={{ x: x2, y: y2 }}
|
|
animate={{
|
|
scale: [1, 1.1, 1],
|
|
rotate: [0, -60, 0],
|
|
}}
|
|
transition={{ duration: 30, repeat: Infinity, ease: "linear" }}
|
|
/>
|
|
<motion.div
|
|
className="absolute bottom-[-10%] left-[20%] w-[45vw] h-[45vw] bg-liquid-rose/30 rounded-full blur-[80px] mix-blend-multiply opacity-70"
|
|
style={{ x: x3, y: y3 }}
|
|
animate={{
|
|
scale: [1, 1.3, 1],
|
|
rotate: [0, 45, 0]
|
|
}}
|
|
transition={{ duration: 35, repeat: Infinity, ease: "linear" }}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|