This commit is contained in:
VizoleLabs 2024-04-09 03:26:18 +00:00
commit 005f63aeeb
4 changed files with 152 additions and 7 deletions

View file

@ -332,7 +332,7 @@ export default function Web() {
<ImageFilter />
</section>
<section className="bg-[#0f172a] dark:bg-gray-900">
<section className="bg-[#0f172a] dark:bg-gray-900 md:pt-[8%] lg:pt-[5%]">
<div className="mx-auto max-w-screen-md px-4 py-8 lg:py-16">
<h2 className="mb-4 text-center text-4xl font-extrabold capitalize leading-none tracking-tight text-white md:text-4xl xl:text-5xl">
Contact Us

View file

@ -4,6 +4,7 @@ import { Button } from "components/Button/Button"
import { useState } from "react"
import { Image } from "./image"
import { FilterableData } from "./FilterableData"
import { CardBody, CardContainer, CardItem } from "components/Ui/Card"
import { motion } from "framer-motion" // Import motion
const ImageFilter = () => {
@ -43,12 +44,16 @@ const ImageFilter = () => {
: "hidden" /* Hide if not matched */
}`}
>
<Image
className="h-[400px] w-full overflow-hidden rounded-lg"
image={item.src}
alt={item.name}
objectCover="object-cover"
/>
<CardContainer>
<CardBody>
<Image
className="h-[400px] w-full overflow-hidden rounded-lg"
image={item.src}
alt={item.name}
objectCover="object-cover"
/>
</CardBody>
</CardContainer>
</motion.div>
))}
</main>

125
components/Ui/Card.tsx Normal file
View file

@ -0,0 +1,125 @@
"use client"
import { cn } from "./../../utils/cn"
import Image from "next/image"
import React, { createContext, useState, useContext, useRef, useEffect } from "react"
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: "1000px",
}}
>
<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("h-full w-full [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-full 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
}

View file

@ -45,6 +45,7 @@
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.1.tgz"
integrity sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==
"@babel/core@^7.0.0", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.13.16", "@babel/core@^7.16.0", "@babel/core@^7.21.3", "@babel/core@^7.22.0", "@babel/core@^7.22.5", "@babel/core@^7.22.9", "@babel/core@^7.23.3", "@babel/core@^7.7.5":
"@babel/core@^7.0.0", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.13.16", "@babel/core@^7.16.0", "@babel/core@^7.21.3", "@babel/core@^7.22.0", "@babel/core@^7.22.5", "@babel/core@^7.22.9", "@babel/core@^7.23.3", "@babel/core@^7.7.5":
version "7.24.3"
resolved "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz"
@ -17365,6 +17366,20 @@ string_decoder@~1.1.1:
dependencies:
safe-buffer "~5.1.0"
string_decoder@^1.1.1, string_decoder@^1.3.0:
version "1.3.0"
resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz"
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
dependencies:
safe-buffer "~5.2.0"
string_decoder@~1.1.1:
version "1.1.1"
resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz"
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
dependencies:
safe-buffer "~5.1.0"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"