diff --git a/src/components/Projects.tsx b/src/components/Projects.tsx index 1faddca..d89722a 100644 --- a/src/components/Projects.tsx +++ b/src/components/Projects.tsx @@ -8,9 +8,11 @@ import { supabase } from '@/lib/supabase/client' import { ParallaxScroll } from './ui/parallax-scroll' export interface Project { + id: string title: string link: string thumbnail: string + description: string } const Projects = () => { @@ -33,8 +35,6 @@ const Projects = () => { className={` py-10 - lg:py-40 - md:py-20 `} > diff --git a/src/components/ui/3d-card.tsx b/src/components/ui/3d-card.tsx new file mode 100644 index 0000000..819ff15 --- /dev/null +++ b/src/components/ui/3d-card.tsx @@ -0,0 +1,155 @@ +'use client' + +import Image from 'next/image' +import type React from 'react' +import { createContext, useContext, useEffect, useRef, useState } from 'react' + +import { cn } from '@/lib/utils' + +const MouseEnterContext = createContext< + [boolean, React.Dispatch>] | undefined +>(undefined) + +export const CardContainer = ({ + children, + className, + containerClassName, +}: { + children?: React.ReactNode + className?: string + containerClassName?: string +}) => { + const containerRef = useRef(null) + const [isMouseEntered, setIsMouseEntered] = useState(false) + + const handleMouseMove = (e: React.MouseEvent) => { + if (!containerRef.current) return + const { left, top, width, height } = + containerRef.current.getBoundingClientRect() + const x = (e.clientX - left - width / 2) / 25 + const y = (e.clientY - top - height / 2) / 25 + containerRef.current.style.transform = `rotateY(${x}deg) rotateX(${y}deg)` + } + + const handleMouseEnter = (e: React.MouseEvent) => { + setIsMouseEntered(true) + if (!containerRef.current) return + } + + const handleMouseLeave = (e: React.MouseEvent) => { + if (!containerRef.current) return + setIsMouseEntered(false) + containerRef.current.style.transform = `rotateY(0deg) rotateX(0deg)` + } + return ( + +
+
+ {children} +
+
+
+ ) +} + +export const CardBody = ({ + children, + className, +}: { + children: React.ReactNode + className?: string +}) => { + return ( +
*]:[transform-style:preserve-3d] + + [transform-style:preserve-3d] + `, + className, + )} + > + {children} +
+ ) +} + +export const CardItem = ({ + as: Tag = 'div', + children, + className, + translateX = 0, + translateY = 0, + translateZ = 0, + rotateX = 0, + rotateY = 0, + rotateZ = 0, + ...rest +}: { + as?: React.ElementType + children: React.ReactNode + className?: string + translateX?: number | string + translateY?: number | string + translateZ?: number | string + rotateX?: number | string + rotateY?: number | string + rotateZ?: number | string + [key: string]: any +}) => { + const ref = useRef(null) + const [isMouseEntered] = useMouseEnter() + + useEffect(() => { + handleAnimations() + }, [isMouseEntered]) + + const handleAnimations = () => { + if (!ref.current) return + if (isMouseEntered) { + ref.current.style.transform = `translateX(${translateX}px) translateY(${translateY}px) translateZ(${translateZ}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) rotateZ(${rotateZ}deg)` + } else { + ref.current.style.transform = `translateX(0px) translateY(0px) translateZ(0px) rotateX(0deg) rotateY(0deg) rotateZ(0deg)` + } + } + + return ( + + {children} + + ) +} + +// Create a hook to use the context +export const useMouseEnter = () => { + const context = useContext(MouseEnterContext) + if (context === undefined) { + throw new Error('useMouseEnter must be used within a MouseEnterProvider') + } + return context +} diff --git a/src/components/ui/parallax-scroll-2.tsx b/src/components/ui/parallax-scroll-2.tsx index 3364562..c7687f7 100644 --- a/src/components/ui/parallax-scroll-2.tsx +++ b/src/components/ui/parallax-scroll-2.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ "use client"; import { motion,useScroll, useTransform } from "framer-motion"; import Image from "next/image"; diff --git a/src/components/ui/parallax-scroll.tsx b/src/components/ui/parallax-scroll.tsx index e9a69f1..dd53d30 100644 --- a/src/components/ui/parallax-scroll.tsx +++ b/src/components/ui/parallax-scroll.tsx @@ -1,11 +1,14 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ 'use client' import { motion, useScroll, useTransform } from 'framer-motion' import Image from 'next/image' +import Link from 'next/link' import { useRef } from 'react' import { cn } from '@/lib/utils' import { type Project } from '../Projects' +import { CardBody, CardContainer, CardItem } from './3d-card' export const ParallaxScroll = ({ projects, @@ -53,21 +56,56 @@ export const ParallaxScroll = ({ > {projects.map((el, idx) => (
-
- + -
-

- {el.title} -

+ > + + {el.title} + + + thumbnail + +
+ + View more → + +
+ +
))} @@ -84,57 +122,201 @@ export const ParallaxScroll = ({
{firstPart.map((el, idx) => ( - thumbnail -

- {el.title} -

+ + + + {el.title} + + + {el.description} + + + thumbnail + +
+ + View more → + +
+
+
))}
{secondPart.map((el, idx) => ( - thumbnail -

- {el.title} -

+ + + + {el.title} + + + {el.description} + + + thumbnail + +
+ + View more → + +
+
+
))}
{thirdPart.map((el, idx) => ( - thumbnail -

- {el.title} -

+ + + + {el.title} + + + {el.description} + + + thumbnail + +
+ + View more → + +
+
+
))}