feat: Add multiple UI components to the codebase
This commit includes several User Interface components such as Button, DropdownMenu, FlipWords, HeroParallax, Input, Label, NavigationMenu and ToastBox. Each component was developed individually and has different attributes and behaviors. This will significantly improve the user experience and interactivity of the application.
This commit is contained in:
147
src/components/ui/hero-parallax.tsx
Normal file
147
src/components/ui/hero-parallax.tsx
Normal file
@@ -0,0 +1,147 @@
|
||||
"use client";
|
||||
import React from "react";
|
||||
import {
|
||||
motion,
|
||||
useScroll,
|
||||
useTransform,
|
||||
useSpring,
|
||||
MotionValue,
|
||||
} from "framer-motion";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
|
||||
interface HeroParallaxProps {
|
||||
products: product[];
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
interface product {
|
||||
title: string;
|
||||
link: string;
|
||||
thumbnail: string;
|
||||
}
|
||||
|
||||
export const HeroParallax = ({ products, children }: HeroParallaxProps ) => {
|
||||
const firstRow = products.slice(0, 5);
|
||||
const secondRow = products.slice(5, 10);
|
||||
const thirdRow = products.slice(10, 15);
|
||||
const ref = React.useRef(null);
|
||||
const { scrollYProgress } = useScroll({
|
||||
target: ref,
|
||||
offset: ["start start", "end start"],
|
||||
});
|
||||
|
||||
const springConfig = { stiffness: 300, damping: 30, bounce: 100 };
|
||||
|
||||
const translateX = useSpring(
|
||||
useTransform(scrollYProgress, [0, 1], [0, 1000]),
|
||||
springConfig
|
||||
);
|
||||
const translateXReverse = useSpring(
|
||||
useTransform(scrollYProgress, [0, 1], [0, -1000]),
|
||||
springConfig
|
||||
);
|
||||
const rotateX = useSpring(
|
||||
useTransform(scrollYProgress, [0, 0.2], [15, 0]),
|
||||
springConfig
|
||||
);
|
||||
const opacity = useSpring(
|
||||
useTransform(scrollYProgress, [0, 0.2], [0.2, 1]),
|
||||
springConfig
|
||||
);
|
||||
const rotateZ = useSpring(
|
||||
useTransform(scrollYProgress, [0, 0.2], [20, 0]),
|
||||
springConfig
|
||||
);
|
||||
const translateY = useSpring(
|
||||
useTransform(scrollYProgress, [0, 0.2], [-700, 500]),
|
||||
springConfig
|
||||
);
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className="h-[300vh] py-40 overflow-hidden antialiased relative flex flex-col self-auto [perspective:1000px] [transform-style:preserve-3d]"
|
||||
>
|
||||
{children}
|
||||
<motion.div
|
||||
style={{
|
||||
rotateX,
|
||||
rotateZ,
|
||||
translateY,
|
||||
opacity,
|
||||
}}
|
||||
className=""
|
||||
>
|
||||
<motion.div className="flex flex-row-reverse space-x-reverse space-x-20 mb-20">
|
||||
{firstRow.map((product) => (
|
||||
<ProductCard
|
||||
product={product}
|
||||
translate={translateX}
|
||||
key={product.title}
|
||||
/>
|
||||
))}
|
||||
</motion.div>
|
||||
<motion.div className="flex flex-row mb-20 space-x-20 ">
|
||||
{secondRow.map((product) => (
|
||||
<ProductCard
|
||||
product={product}
|
||||
translate={translateXReverse}
|
||||
key={product.title}
|
||||
/>
|
||||
))}
|
||||
</motion.div>
|
||||
<motion.div className="flex flex-row-reverse space-x-reverse space-x-20">
|
||||
{thirdRow.map((product) => (
|
||||
<ProductCard
|
||||
product={product}
|
||||
translate={translateX}
|
||||
key={product.title}
|
||||
/>
|
||||
))}
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const ProductCard = ({
|
||||
product,
|
||||
translate,
|
||||
}: {
|
||||
product: {
|
||||
title: string;
|
||||
link: string;
|
||||
thumbnail: string;
|
||||
};
|
||||
translate: MotionValue<number>;
|
||||
}) => {
|
||||
return (
|
||||
<motion.div
|
||||
style={{
|
||||
x: translate,
|
||||
}}
|
||||
whileHover={{
|
||||
y: -20,
|
||||
}}
|
||||
key={product.title}
|
||||
className="group/product h-96 w-[30rem] relative flex-shrink-0"
|
||||
>
|
||||
<Link
|
||||
href={product.link}
|
||||
className="block group-hover/product:shadow-2xl "
|
||||
>
|
||||
<Image
|
||||
src={product.thumbnail}
|
||||
height="600"
|
||||
width="600"
|
||||
className="object-cover object-left-top absolute h-full w-full rounded inset-0"
|
||||
alt={product.title}
|
||||
/>
|
||||
</Link>
|
||||
<div className="absolute inset-0 h-full w-full opacity-0 group-hover/product:opacity-80 bg-black pointer-events-none"></div>
|
||||
<h2 className="absolute bottom-4 left-4 opacity-0 group-hover/product:opacity-100 text-white">
|
||||
{product.title}
|
||||
</h2>
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user