Skip to content

Commit

Permalink
Merge pull request #340 from chitraa-cj/review
Browse files Browse the repository at this point in the history
Review us sectio UI - Scrolling
  • Loading branch information
subhadeeproy3902 authored Jun 22, 2024
2 parents d5dcf85 + 0054a78 commit e578427
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 154 deletions.
46 changes: 46 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,52 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@keyframes scroll {
0% {
transform: translateY(0);
}
100% {
transform: translateY(-50%);
}
}

.scroll-column {
display: flex;
flex-direction: column;
}

.scroll-column.fast {
animation: scroll 10s linear infinite;
}

.scroll-column.slow {
animation: scroll 20s linear infinite;
}

.neon-star {
color: #ff8c00; /* neon orange */
fill: #ff8c00; /* neon orange */
text-shadow:
0 0 5px #ff8c00,
0 0 10px #ff8c00,
0 0 15px #ff8c00,
0 0 20px #ff8c00,
0 0 25px #ff8c00,
0 0 30px #ff8c00;
}

body.dark-mode {
background-color: #121212;
color: #ffffff;
}

body.dark-mode .bg-white {
background-color: #1e1e1e;
}

body.dark-mode .text-gray-800 {
color: #ffffff;
}

@layer base {
:root {
Expand Down
93 changes: 64 additions & 29 deletions src/components/shared/customerreviews.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,34 +18,15 @@ import { Textarea } from "@/components/ui/textarea";
import { ReviewCarousel } from "../ui/reviewcarousel";

const testimonials2 = [
{
quote:
"Blox AI has completely transformed the way we visualize ideas within our organization. The effortless creation tools make it simple for even non-technical team members to create professional-looking visuals and share ideas with ease and efficiency",
name: "Stacy Stone",
title: "CEO at Company",
imgSrc: "https://i.pravatar.cc/120?img=1",
},
{
quote:
"Blox AI has become an indispensable tool for our team's workflow. Whether we're brainstorming new ideas, mapping out user journeys, or documenting complex algorithms Blox AI provides us with the versatility and functionality we need.",
name: "Andrew Jettpace",
title: "CEO at Company",
imgSrc: "https://i.pravatar.cc/120?img=2",
},
{
quote:
"Blox AI has truly impressed me with its versatility and reliability. Whether I'm working on a simple flowchart or a complex diagram, Blox AI provides the tools I need to bring ideas to life The integration of the Gemini AI model for explanations adds a layer of intelligence to it",
name: "Edgar Allan Poe",
title: "CEO at Company",
imgSrc: "https://i.pravatar.cc/120?img=3",
},
{
quote:
"I've been using Blox AI for a while now, and it has become an integral part of my workflow. The ease of creating flowcharts, coupled with the AI explanation feature has greatly enhanced productivity and sharing option allows me to effortlessly collaborate",
name: "Cornelius Sheppard",
title: "CEO at Company",
imgSrc: "https://i.pravatar.cc/120?img=4",
},
{ quote: "This is literally the most important app you will ever download in your life. Get on this before it’s so popular that everyone else is getting these tips too.", name: "SarahLuvzCash" },
{ quote: "I’m 13 and I’m rich. I love that with Pocket’s transaction anonymization I could sign up and start trading when I was 12 years old. I had a million dollars before I had armpit hair!", name: "RichieRich" },
{ quote: "Started an investment firm. I charge clients a 3% management fee and just throw all their investments into Pocket. Easy money!", name: "TheCountOfMonteChristo" },
{ quote: "Too good to be true. I was making money so fast with Pocket that it felt like a scam. But I sold my shares and withdrew the money and it’s really there, right in my bank account. This app is crazy!", name: "LazyRich99" },
{ quote: "Quit my job. I downloaded Pocket three days ago and quit my job today. I can’t believe no one else thought to build a stock trading app that works this way!", name: "RichieRich" },
{ quote: "Don’t download this app. Unless you want to have the best life ever! I am literally writing this from a yacht.", name: "JeffBezos" },
{ quote: "It’s like a superpower. Every tip Pocket has sent me has paid off. It’s like playing Blackjack but knowing exactly what card is coming next!", name: "ClarkKent" },
{ quote: "Don’t download this app. Unless you want to have the best life ever! I am literally writing this from a yacht.", name: "JeffBezos" },
{ quote: "It’s like a superpower. Every tip Pocket has sent me has paid off. It’s like playing Blackjack but knowing exactly what card is coming next!", name: "ClarkKent" }
];

const formSchema = z.object({
Expand Down Expand Up @@ -96,7 +77,7 @@ export default function Review() {
<p className="text-2xl md:text-4xl font-semibold py-5">
Read what our customers love about us.
</p>
<ReviewCarousel items={testimonials2} direction="left" speed="slow" />
<ReviewCarousel items={testimonials2} />
</div>
<div className="flex w-full text-2xl flex-col items-center p-10 md:text-sm">
<p className="text-xl md:text-2xl py-5 opacity-75">
Expand Down Expand Up @@ -148,6 +129,59 @@ export default function Review() {
)}
/>

<FormField
control={form.control}
name="feedbackType"
render={({ field }) => (
<FormItem>
<FormLabel>Feedback Type</FormLabel>
<FormControl>
<select
{...field}
onChange={(e) => {
field.onChange(e);
handleFeedbackTypeChange(e.target.value);
}}
className="form-select mt-1 block w-full p-2 border border-gray-300 rounded-md"
>
<option value="">Select Feedback Type</option>
<option value="Complaint">Complaint</option>
<option value="Suggestion">Suggestion</option>
<option value="Appreciation">Appreciation</option>
<option value="Other">Other</option>
</select>
</FormControl>
<FormMessage />
</FormItem>
)}
/>

{showOtherFeedback && (
<FormField
control={form.control}
name="otherFeedback"
render={({ field }) => (
<FormItem>
<FormLabel>Other Feedback</FormLabel>
<FormControl>
<Input placeholder="Your feedback" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
)}

<FormField
control={form.control}
name="feedback"
render={({ field }) => (
<FormItem>
<FormLabel>Feedback</FormLabel>
<FormControl>
<Textarea
placeholder="Please leave your feedback here"

<FormField
control={form.control}
name="feedbackType"
Expand Down Expand Up @@ -213,6 +247,7 @@ export default function Review() {
)}
/>

<Button type="submit">Submit</Button>
<Button type="submit" className="w-full">
<b>SUBMIT</b>
</Button>
Expand Down
159 changes: 42 additions & 117 deletions src/components/ui/reviewcarousel.tsx
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>
);
};
14 changes: 6 additions & 8 deletions tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const config = {
'./components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
'./src/**/*.{ts,tsx}',
],
],
prefix: "",
theme: {
container: {
Expand Down Expand Up @@ -67,21 +67,19 @@ const config = {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: "0" },
},
scroll: {
to: {
transform: "translate(calc(-50% - 0.5rem))",
},
"scroll-vertical": {
'0%': { transform: 'translateY(0)' },
'100%': { transform: 'translateY(-100%)' },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
scroll:
"scroll var(--animation-duration, 40s) var(--animation-direction, forwards) linear infinite",
"scroll-vertical": "scroll-vertical 20s linear infinite",
},
},
},
plugins: [require("tailwindcss-animate")],
} satisfies Config

export default config
export default config

0 comments on commit e578427

Please sign in to comment.