Skip to content

Commit

Permalink
update: new projects
Browse files Browse the repository at this point in the history
  • Loading branch information
DangTinh422003 committed Nov 12, 2024
1 parent ea530b8 commit faccfa8
Show file tree
Hide file tree
Showing 4 changed files with 392 additions and 54 deletions.
4 changes: 2 additions & 2 deletions src/components/Projects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = () => {
Expand All @@ -33,8 +35,6 @@ const Projects = () => {
className={`
py-10
lg:py-40
md:py-20
`}
>
Expand Down
155 changes: 155 additions & 0 deletions src/components/ui/3d-card.tsx
Original file line number Diff line number Diff line change
@@ -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<React.SetStateAction<boolean>>] | undefined
>(undefined)

export const CardContainer = ({
children,
className,
containerClassName,
}: {
children?: React.ReactNode
className?: string
containerClassName?: string
}) => {
const containerRef = useRef<HTMLDivElement>(null)
const [isMouseEntered, setIsMouseEntered] = useState(false)

const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
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<HTMLDivElement>) => {
setIsMouseEntered(true)
if (!containerRef.current) return
}

const handleMouseLeave = (e: React.MouseEvent<HTMLDivElement>) => {
if (!containerRef.current) return
setIsMouseEntered(false)
containerRef.current.style.transform = `rotateY(0deg) rotateX(0deg)`
}
return (
<MouseEnterContext.Provider value={[isMouseEntered, setIsMouseEntered]}>
<div
className={cn('flex items-center justify-center', containerClassName)}
style={{
perspective: '1500px',
}}
>
<div
ref={containerRef}
onMouseEnter={handleMouseEnter}
onMouseMove={handleMouseMove}
onMouseLeave={handleMouseLeave}
className={cn(
`
relative flex items-center justify-center transition-all
duration-200 ease-linear
`,
className,
)}
style={{
transformStyle: 'preserve-3d',
}}
>
{children}
</div>
</div>
</MouseEnterContext.Provider>
)
}

export const CardBody = ({
children,
className,
}: {
children: React.ReactNode
className?: string
}) => {
return (
<div
className={cn(
`
[&>*]:[transform-style:preserve-3d]
[transform-style:preserve-3d]
`,
className,
)}
>
{children}
</div>
)
}

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<HTMLDivElement>(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 (
<Tag
ref={ref}
className={cn('w-fit transition duration-200 ease-linear', className)}
{...rest}
>
{children}
</Tag>
)
}

// 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
}
1 change: 1 addition & 0 deletions src/components/ui/parallax-scroll-2.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand Down
Loading

0 comments on commit faccfa8

Please sign in to comment.