Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aea4d2075a | |||
| 49c135322c | |||
| 1bc569a591 | |||
| 5bffa247ac | |||
| 9d54164392 | |||
| fe728c129f | |||
| 58c0e016b7 | |||
| 0f84616d2d | |||
| 9efac29bb7 |
@@ -3,22 +3,22 @@
|
||||
/* --vw is set by ThemeProvider */
|
||||
|
||||
/* --background: #f7f6f7;;
|
||||
--card: #faf9fb;;
|
||||
--foreground: #2d3e52;;
|
||||
--primary-cta: #6b9fd9;;
|
||||
--secondary-cta: #f5f3f7;;
|
||||
--accent: #b8d9f0;;
|
||||
--background-accent: #d4e4f0;; */
|
||||
--card: #faf9f7;;
|
||||
--foreground: #52423d;;
|
||||
--primary-cta: #d9956b;;
|
||||
--secondary-cta: #f7f5f3;;
|
||||
--accent: #f0d9b8;;
|
||||
--background-accent: #f0e4d4;; */
|
||||
|
||||
--background: #faf8fb;;
|
||||
--card: #faf9fb;;
|
||||
--foreground: #2d3e52;;
|
||||
--primary-cta: #6b9fd9;;
|
||||
--background: #fbf8f5;;
|
||||
--card: #faf9f7;;
|
||||
--foreground: #52423d;;
|
||||
--primary-cta: #d9956b;;
|
||||
--primary-cta-text: #f7f6f7;;
|
||||
--secondary-cta: #f5f3f7;;
|
||||
--secondary-cta: #f7f5f3;;
|
||||
--secondary-cta-text: #0c1325;;
|
||||
--accent: #b8d9f0;;
|
||||
--background-accent: #d4e4f0;;
|
||||
--accent: #f0d9b8;;
|
||||
--background-accent: #f0e4d4;;
|
||||
|
||||
/* text sizing - set by ThemeProvider */
|
||||
/* --text-2xs: clamp(0.465rem, 0.62vw, 0.62rem);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"use client";
|
||||
|
||||
import { memo } from "react";
|
||||
import { memo, useState } from "react";
|
||||
import CardStack from "@/components/cardStack/CardStack";
|
||||
import MediaContent from "@/components/shared/MediaContent";
|
||||
import { cls } from "@/lib/utils";
|
||||
import { Star } from "lucide-react";
|
||||
import { Star, Heart } from "lucide-react";
|
||||
import type { LucideIcon } from "lucide-react";
|
||||
import type { ButtonConfig, ButtonAnimationType, CardAnimationTypeWith3D, GridVariant, TitleSegment, TextboxLayout, InvertedBackground } from "@/components/cardStack/types";
|
||||
|
||||
@@ -18,6 +18,8 @@ type Testimonial = {
|
||||
videoSrc?: string;
|
||||
imageAlt?: string;
|
||||
videoAriaLabel?: string;
|
||||
backText?: string;
|
||||
testimonialText?: string;
|
||||
};
|
||||
|
||||
interface TestimonialCardOneProps {
|
||||
@@ -69,6 +71,7 @@ interface TestimonialCardProps {
|
||||
nameClassName?: string;
|
||||
roleClassName?: string;
|
||||
companyClassName?: string;
|
||||
backTextClassName?: string;
|
||||
}
|
||||
|
||||
const TestimonialCard = memo(({
|
||||
@@ -80,41 +83,84 @@ const TestimonialCard = memo(({
|
||||
nameClassName = "",
|
||||
roleClassName = "",
|
||||
companyClassName = "",
|
||||
backTextClassName = "",
|
||||
}: TestimonialCardProps) => {
|
||||
return (
|
||||
<div className={cls("relative h-full rounded-theme-capped overflow-hidden group", cardClassName)}>
|
||||
<MediaContent
|
||||
imageSrc={testimonial.imageSrc}
|
||||
videoSrc={testimonial.videoSrc}
|
||||
imageAlt={testimonial.imageAlt || testimonial.name}
|
||||
videoAriaLabel={testimonial.videoAriaLabel || testimonial.name}
|
||||
imageClassName={cls("relative z-1 w-full h-full object-cover!", imageClassName)}
|
||||
/>
|
||||
const [isFlipped, setIsFlipped] = useState(false);
|
||||
|
||||
<div className={cls("!absolute z-1 bottom-6 left-6 right-6 card backdrop-blur-xs p-6 flex flex-col gap-3 rounded-theme-capped", overlayClassName)}>
|
||||
<div className={cls("relative z-1 flex gap-1", ratingClassName)}>
|
||||
{Array.from({ length: 5 }).map((_, index) => (
|
||||
<Star
|
||||
key={index}
|
||||
className={cls(
|
||||
"h-5 w-auto text-accent",
|
||||
index < testimonial.rating ? "fill-accent" : "fill-transparent"
|
||||
)}
|
||||
strokeWidth={1.5}
|
||||
/>
|
||||
))}
|
||||
return (
|
||||
<div
|
||||
className={cls("relative h-full rounded-theme-capped overflow-hidden group cursor-pointer", cardClassName)}
|
||||
style={{
|
||||
perspective: "1000px",
|
||||
}}
|
||||
onMouseEnter={() => setIsFlipped(true)}
|
||||
onMouseLeave={() => setIsFlipped(false)}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
transformStyle: "preserve-3d",
|
||||
transform: isFlipped ? "rotateY(180deg)" : "rotateY(0deg)",
|
||||
transition: "transform 0.6s ease-in-out",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
}}
|
||||
>
|
||||
{/* Front side */}
|
||||
<div
|
||||
style={{
|
||||
backfaceVisibility: "hidden",
|
||||
WebkitBackfaceVisibility: "hidden",
|
||||
}}
|
||||
className="w-full h-full"
|
||||
>
|
||||
<MediaContent
|
||||
imageSrc={testimonial.imageSrc}
|
||||
videoSrc={testimonial.videoSrc}
|
||||
imageAlt={testimonial.imageAlt || testimonial.name}
|
||||
videoAriaLabel={testimonial.videoAriaLabel || testimonial.name}
|
||||
imageClassName={cls("relative z-1 w-full h-full object-cover!", imageClassName)}
|
||||
/>
|
||||
|
||||
<div className={cls("!absolute z-1 bottom-6 left-6 right-6 card backdrop-blur-xs p-6 flex flex-col gap-3 rounded-theme-capped", overlayClassName)}>
|
||||
<div className={cls("relative z-1 flex gap-1", ratingClassName)}>
|
||||
{Array.from({ length: 5 }).map((_, index) => (
|
||||
<Star
|
||||
key={index}
|
||||
className={cls(
|
||||
"h-5 w-auto text-accent",
|
||||
index < testimonial.rating ? "fill-accent" : "fill-transparent"
|
||||
)}
|
||||
strokeWidth={1.5}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<h3 className={cls("relative z-1 text-2xl font-medium text-foreground leading-[1.1] mt-1", nameClassName)}>
|
||||
{testimonial.name}
|
||||
</h3>
|
||||
|
||||
<div className="relative z-1 flex flex-col gap-1">
|
||||
<p className={cls("text-base text-foreground leading-[1.1]", roleClassName)}>
|
||||
{testimonial.role}
|
||||
</p>
|
||||
<p className={cls("text-base text-foreground leading-[1.1]", companyClassName)}>
|
||||
{testimonial.company}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 className={cls("relative z-1 text-2xl font-medium text-foreground leading-[1.1] mt-1", nameClassName)}>
|
||||
{testimonial.name}
|
||||
</h3>
|
||||
|
||||
<div className="relative z-1 flex flex-col gap-1">
|
||||
<p className={cls("text-base text-foreground leading-[1.1]", roleClassName)}>
|
||||
{testimonial.role}
|
||||
</p>
|
||||
<p className={cls("text-base text-foreground leading-[1.1]", companyClassName)}>
|
||||
{testimonial.company}
|
||||
{/* Back side */}
|
||||
<div
|
||||
style={{
|
||||
backfaceVisibility: "hidden",
|
||||
WebkitBackfaceVisibility: "hidden",
|
||||
transform: "rotateY(180deg)",
|
||||
}}
|
||||
className={cls("absolute inset-0 w-full h-full card backdrop-blur-xs p-6 flex flex-col gap-3 rounded-theme-capped justify-center items-center", backTextClassName)}
|
||||
>
|
||||
<p className="text-base text-foreground leading-relaxed text-center">
|
||||
{testimonial.backText || "Hover to see more"}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -164,7 +210,22 @@ const TestimonialCardOne = ({
|
||||
textBoxButtonTextClassName = "",
|
||||
}: TestimonialCardOneProps) => {
|
||||
return (
|
||||
<CardStack
|
||||
<div className="relative">
|
||||
{/* Decorative hearts around section */}
|
||||
<div className="absolute -top-8 left-1/4 text-red-500 opacity-60 animate-pulse">
|
||||
<Heart size={24} fill="currentColor" />
|
||||
</div>
|
||||
<div className="absolute -top-6 right-1/4 text-red-500 opacity-50 animate-pulse" style={{ animationDelay: "0.5s" }}>
|
||||
<Heart size={20} fill="currentColor" />
|
||||
</div>
|
||||
<div className="absolute -bottom-8 left-1/3 text-red-500 opacity-60 animate-pulse" style={{ animationDelay: "1s" }}>
|
||||
<Heart size={22} fill="currentColor" />
|
||||
</div>
|
||||
<div className="absolute -bottom-6 right-1/3 text-red-500 opacity-50 animate-pulse" style={{ animationDelay: "0.3s" }}>
|
||||
<Heart size={18} fill="currentColor" />
|
||||
</div>
|
||||
|
||||
<CardStack
|
||||
mode={carouselMode}
|
||||
gridVariant={gridVariant}
|
||||
uniformGridCustomHeightClasses={uniformGridCustomHeightClasses}
|
||||
@@ -208,9 +269,11 @@ const TestimonialCardOne = ({
|
||||
nameClassName={nameClassName}
|
||||
roleClassName={roleClassName}
|
||||
companyClassName={companyClassName}
|
||||
backTextClassName=""
|
||||
/>
|
||||
))}
|
||||
</CardStack>
|
||||
</CardStack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user