-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #340 from chitraa-cj/review
Review us sectio UI - Scrolling
- Loading branch information
Showing
4 changed files
with
158 additions
and
154 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,126 +1,51 @@ | ||
"use client"; | ||
import React from "react"; | ||
import { Star } from "lucide-react"; | ||
|
||
import { cn } from "@/lib/utils"; | ||
import React, { useEffect, useState } from "react"; | ||
import Image from "next/image"; | ||
import { imageLoader } from "@/lib/imageLoader"; | ||
interface ReviewItem { | ||
quote: string; | ||
name: string; | ||
} | ||
|
||
export const ReviewCarousel = ({ | ||
items, | ||
direction = "left", | ||
speed = "fast", | ||
pauseOnHover = true, | ||
className, | ||
}: { | ||
items: { | ||
quote: string; | ||
name: string; | ||
title: string; | ||
imgSrc: string; | ||
}[]; | ||
direction?: "left" | "right"; | ||
speed?: "fast" | "normal" | "slow"; | ||
pauseOnHover?: boolean; | ||
className?: string; | ||
}) => { | ||
const containerRef = React.useRef<HTMLDivElement>(null); | ||
const scrollerRef = React.useRef<HTMLUListElement>(null); | ||
|
||
useEffect(() => { | ||
addAnimation(); | ||
}, []); | ||
|
||
const [start, setStart] = useState(false); | ||
|
||
function addAnimation() { | ||
if (containerRef.current && scrollerRef.current) { | ||
const scrollerContent = Array.from(scrollerRef.current.children); | ||
|
||
scrollerContent.forEach((item) => { | ||
const duplicatedItem = item.cloneNode(true); | ||
if (scrollerRef.current) { | ||
scrollerRef.current.appendChild(duplicatedItem); | ||
} | ||
}); | ||
|
||
getDirection(); | ||
getSpeed(); | ||
setStart(true); | ||
} | ||
} | ||
|
||
const getDirection = () => { | ||
if (containerRef.current) { | ||
containerRef.current.style.setProperty( | ||
"--animation-direction", | ||
direction === "left" ? "forwards" : "reverse" | ||
); | ||
} | ||
}; | ||
|
||
const getSpeed = () => { | ||
if (containerRef.current) { | ||
containerRef.current.style.setProperty( | ||
"--animation-duration", | ||
speed === "fast" ? "20s" : speed === "normal" ? "40s" : "90s" | ||
); | ||
} | ||
}; | ||
interface ReviewCarouselProps { | ||
items: ReviewItem[]; | ||
} | ||
|
||
const VerticalScrollColumn: React.FC<{ items: ReviewItem[]; speed: string }> = ({ items, speed }) => { | ||
return ( | ||
<div | ||
ref={containerRef} | ||
className={cn( | ||
"scroller relative z-20 max-w-7xl overflow-hidden dark:[mask-image:linear-gradient(to_right,transparent,white_20%,white_80%,transparent)]", | ||
className | ||
)} | ||
> | ||
<ul | ||
ref={scrollerRef} | ||
className={cn( | ||
"flex min-w-full shrink-0 gap-4 py-4 w-max flex-nowrap", | ||
start && "animate-scroll", | ||
pauseOnHover && "hover:[animation-play-state:paused]" | ||
)} | ||
> | ||
{items.map((item, idx) => ( | ||
<li | ||
className="w-[250px] md:w-[350px] lg:w-[450px] max-w-full relative rounded-2xl border border-b-2 flex-shrink-0 border-slate-700 px-4 md:px-8 py-6 bg-orange-100 dark:bg-secondary" | ||
key={item.name} | ||
> | ||
<blockquote> | ||
<div | ||
aria-hidden="true" | ||
className="user-select-none -z-1 pointer-events-none absolute -left-0.5 -top-0.5 h-[calc(100%_+_4px)] w-[calc(100%_+_4px)]" | ||
></div> | ||
<span className="relative z-20 text-sm md:text-base leading-[1.6] dark:text-gray-100 text-black font-normal"> | ||
{item.quote} | ||
</span> | ||
<div className="relative z-20 mt-6 flex flex-row items-center"> | ||
<span className="inline-flex rounded-full px-3"> | ||
<Image | ||
loader={imageLoader} | ||
className="h-10 w-10 md:h-12 md:w-12 rounded-full" | ||
height={40} | ||
width={40} | ||
alt={item.name} | ||
src={item.imgSrc} | ||
loading="lazy" | ||
/> | ||
</span> | ||
<span className="flex flex-col gap-1"> | ||
<span className="text-sm md:text-base leading-[1.6] dark:text-gray-300 text-black font-semibold"> | ||
{item.name} | ||
</span> | ||
<span className="text-sm md:text-base leading-[1.6] dark:text-gray-300 text-black font-normal"> | ||
{item.title} | ||
</span> | ||
</span> | ||
<div className="flex flex-col"> | ||
<div className={`scroll-column ${speed}`}> | ||
{items.concat(items).map((item, index) => ( | ||
<div key={index} className="flex flex-col items-start py-4 w-full"> | ||
<div className="bg-white dark:bg-secondary shadow-lg rounded-lg p-6 max-w-sm mx-auto w-full"> | ||
<div className="flex items-center mb-2"> | ||
{Array(5) | ||
.fill(0) | ||
.map((_, i) => ( | ||
<Star key={i} color="orange" fill="orange" className="neon-star" /> | ||
))} | ||
</div> | ||
</blockquote> | ||
</li> | ||
<p className="italic mt-4 text-left text-gray-800 dark:text-gray-200"> | ||
"{item.quote}" | ||
</p> | ||
<p className="font-bold mt-2 text-left text-gray-800 dark:text-gray-200"> | ||
- {item.name} | ||
</p> | ||
</div> | ||
</div> | ||
))} | ||
</ul> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export const ReviewCarousel: React.FC<ReviewCarouselProps> = ({ items }) => { | ||
const columnItems = Math.ceil(items.length / 3); | ||
|
||
return ( | ||
<div className="relative flex justify-center overflow-hidden h-96 w-full space-x-4"> | ||
<VerticalScrollColumn items={items.slice(0, columnItems)} speed="fast" /> | ||
<VerticalScrollColumn items={items.slice(columnItems, columnItems * 2)} speed="slow" /> | ||
<VerticalScrollColumn items={items.slice(columnItems * 2)} speed="fast" /> | ||
</div> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters