Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"@emailjs/browser": "^4.4.1",
"@react-three/drei": "^10.7.4",
"@react-three/fiber": "^9.3.0",
"@tailwindcss/vite": "^4.1.12",
Expand Down
5 changes: 4 additions & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Hero from './sections/Hero'
import About from './sections/About'
import Projects from './sections/Projects'
import Experiences from './sections/Experiences'
import Testimonial from './sections/Testimonial'

const App = () => {
return (
Expand All @@ -14,13 +15,15 @@ const App = () => {
<About/>
<Projects/>
<Experiences/>
<Testimonial/>
<section className="min-h-screen"></section>
<section className="min-h-screen"></section>
<section className="min-h-screen"></section>
<section className="min-h-screen"></section>
<section className="min-h-screen"></section>
<section className="min-h-screen"></section>

{/* service_g8pia9k */}
{/* template_lrhppet */}
{/*experinec*/}
{/*testimonial*/}
{/*contact*/}
Expand Down
40 changes: 40 additions & 0 deletions src/components/Marquee.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { twMerge } from "tailwind-merge";
export default function Marquee({
className,
reverse = false,
pauseOnHover = false,
children,
vertical = false,
repeat = 4,
...props
}) {
return (
<div
{...props}
className={twMerge(
`group flex overflow-hidden p-2 [--duration:40s] [--gap:1rem] [gap:var(--gap)] ${
vertical ? "flex-col" : "flex-row"
}`,
className
)}
>
{Array(repeat)
.fill(0)
.map((_, i) => (
<div
key={i}
className={twMerge(
"flex shrink-0 justify-around [gap:var(--gap)]",
vertical
? "animate-marquee-vertical flex-col"
: "animate-marquee flex-row",
pauseOnHover && "group-hover:[animation-play-state:paused]",
reverse && "[animation-direction:reverse]"
)}
>
{children}
</div>
))}
</div>
);
}
54 changes: 54 additions & 0 deletions src/sections/Testimonial.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { twMerge } from "tailwind-merge";
import Marquee from "../components/Marquee";
import { reviews } from "../constants";
const firstRow = reviews.slice(0, reviews.length / 2);
const secondRow = reviews.slice(reviews.length / 2);

const ReviewCard = ({ img, name, username, body }) => {
return (
<figure
className={twMerge(
"relative h-full w-64 cursor-pointer overflow-hidden rounded-xl border p-4 border-gray-50/[.1] bg-gradient-to-r bg-indigo to-storm hover:bg-royal hover-animation"
)}
>
<div className="flex flex-row items-center gap-2">
<img
className="rounded-full bg-white/10"
width="32"
height="32"
alt=""
src={img}
/>
<div className="flex flex-col">
<figcaption className="text-sm font-medium text-white">
{name}
</figcaption>
<p className="text-xs font-medium text-white/40">{username}</p>
</div>
</div>
<blockquote className="mt-2 text-sm">{body}</blockquote>
</figure>
);
};

export default function Testimonial() {
return (
<div className="items-start mt-25 md:mt-35 c-space">
<h2 className="text-heading">Hear From My Clients</h2>
<div className="relative flex flex-col items-center justify-center w-full mt-12 overflow-hidden">
<Marquee pauseOnHover className="[--duration:20s]">
{firstRow.map((review) => (
<ReviewCard key={review.username} {...review} />
))}
</Marquee>
<Marquee reverse pauseOnHover className="[--duration:20s]">
{secondRow.map((review) => (
<ReviewCard key={review.username} {...review} />
))}
</Marquee>
<div className="absolute inset-y-0 left-0 w-1/4 pointer-events-none bg-gradient-to-r from-primary"></div>
<div className="absolute inset-y-0 right-0 w-1/4 pointer-events-none bg-gradient-to-l from-primary"></div>
</div>
</div>
);
}