Skip to content

Commit

Permalink
merged all carousels so they're one component now (#257)
Browse files Browse the repository at this point in the history
  • Loading branch information
stephanietfong authored Feb 26, 2025
1 parent 12ef157 commit cf09f15
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 277 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { cn } from "@/shared/utils";
import Values from "@components/home/Values";
import ProgramImages from "@components/programs/ProgramImages";
import Testimonials from "@components/programs/Testimonials";
import type { EmblaCarouselType, EmblaEventType, EmblaOptionsType } from "embla-carousel";
import useEmblaCarousel from "embla-carousel-react";
import React, { useCallback, useEffect, useRef } from "react";
import { NextButton, PrevButton, usePrevNextButtons } from "./CarouselArrows";
import ProgramImages from "./ProgramImages";
import Testimonials from "./Testimonials";

const TWEEN_FACTOR_BASE = 0.52;

Expand All @@ -16,12 +17,36 @@ type PropType = {
prog: string;
};

type Value = {
img: string;
icon: string;
value: string;
text: string;
};

type Testimonial = {
name: string;
position: string;
quote: string;
image: string;
};

const checkisValue = (slide: unknown): slide is Value => {
return typeof slide === "object" && slide !== null && "img" in slide && "icon" in slide && "value" in slide && "text" in slide;
};

const checkisTestimonial = (slide: unknown): slide is Testimonial => {
return typeof slide === "object" && slide !== null && "name" in slide && "position" in slide && "quote" in slide && "image" in slide;
};

const TestimonialCarousel: React.FC<PropType> = ({ prog, purpose }) => {
let slides;
if (purpose == "Testimonials") {
slides = Testimonials.find((t) => t.program === prog)?.testimonials ?? [];
} else {
} else if (purpose == "Images") {
slides = ProgramImages.find((i) => i.program === prog)?.images ?? [];
} else {
slides = Values;
}

const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true });
Expand Down Expand Up @@ -92,57 +117,84 @@ const TestimonialCarousel: React.FC<PropType> = ({ prog, purpose }) => {
<div
className={cn(
{
"flex items-center justify-center": purpose === "Testimonials",
"flex items-center justify-center pb-8": purpose === "Testimonials",
},
`relative m-auto pb-8`,
`relative m-auto`,
)}
>
{/* Testimonials have arrows on sides*/}
{purpose === "Testimonials" ? (
<>
<PrevButton onClick={onPrevButtonClick} disabled={prevBtnDisabled} />
<PrevButton onClick={onPrevButtonClick} disabled={prevBtnDisabled} purpose={purpose} />
<div className="absolute left-0 top-0 z-10 ml-[8%] h-full w-16 bg-gradient-to-r from-white to-transparent" />
</>
) : null}

{/* Shadowing for Images and Values */}
{purpose === "Images" ? <div className="absolute left-0 top-0 z-10 h-full w-16 bg-gradient-to-r from-white to-transparent" /> : null}
{purpose === "Values" ? <div className="absolute left-0 top-0 z-10 h-full w-16 bg-gradient-to-r from-black to-transparent" /> : null}

<div className="overflow-hidden" ref={emblaRef}>
<div className="flex touch-pan-y touch-pinch-zoom">
{slides.map((slide, index) => (
<div className="flex min-w-0 flex-[0_0_100%] items-center justify-center [transform:translate3d(0,0,0)] md:flex-[0_0_50%]" key={index}>
<div className="embla__slide__image rounded-2xl bg-gradient-to-r from-saseBlue via-[#7DC242] to-saseGreen p-[4px]">
<div className="embla__slide__image group relative flex items-center justify-center hover:cursor-pointer">
{/* If slide element is not a string, carousel is for testimonials. If it is, carousel is for images */}
{typeof slide != "string" ? (
<img src={slide.image} alt={`Image`} className="aspect-auto rounded-xl" />
) : (
<img src={slide} alt={`Image`} className="aspect-auto rounded-xl" />
)}
{typeof slide != "string" ? (
<div className="absolute inset-0 flex flex-col items-center justify-end rounded-xl bg-saseGray/60 hover:bg-saseGray/90">
<p className="absolute pb-10 font-redhat text-xl font-semibold opacity-100 transition duration-300 group-hover:opacity-0">
{slide.name}
{checkisValue(slide) ? (
<div className="embla__slide__image group relative w-full rounded-2xl hover:cursor-pointer">
<img src={slide.img} alt={`${slide.value} + Image`} className="aspect-auto rounded-xl" />
<div className="absolute inset-0 flex flex-col items-center justify-center rounded-xl bg-saseGray/60 hover:bg-saseGray/85">
<img src={slide.icon} alt={`${slide.value} + Icon`} className="mb-2 transition-opacity duration-300 group-hover:opacity-0" />{" "}
<p className="text-center font-redhat text-3xl font-semibold text-black transition-opacity duration-300 group-hover:opacity-0 md:text-2xl lg:text-3xl">
{slide.value}
</p>
<p className="absolute pb-4 font-redhat text-lg opacity-100 transition duration-300 group-hover:opacity-0">{slide.position}</p>
<p className="flex h-0 w-full items-center justify-center overflow-hidden px-4 text-center font-redhat text-lg font-medium text-black opacity-0 transition-all duration-700 ease-in-out group-hover:h-full group-hover:translate-y-0 group-hover:opacity-100 md:text-sm lg:text-base">
"{slide.quote}"
<p className="absolute bottom-[-20%] px-4 text-center font-redhat text-lg font-medium text-black opacity-0 transition-all duration-500 group-hover:bottom-1/2 group-hover:translate-y-1/2 group-hover:opacity-100 md:text-base lg:text-lg">
{slide.text}
</p>
</div>
) : null}
</div>
</div>
) : (
<div className="embla__slide__image group relative flex items-center justify-center hover:cursor-pointer">
{checkisTestimonial(slide) ? (
<>
<img src={slide.image} alt={`Image`} className="aspect-auto rounded-xl" />
<div className="absolute inset-0 flex flex-col items-center justify-end rounded-xl bg-saseGray/60 hover:bg-saseGray/90">
<p className="absolute pb-10 font-redhat text-xl font-semibold opacity-100 transition duration-300 group-hover:opacity-0">
{slide.name}
</p>
<p className="absolute pb-4 font-redhat text-lg opacity-100 transition duration-300 group-hover:opacity-0">
{slide.position}
</p>
<p className="flex h-0 w-full items-center justify-center overflow-hidden px-4 text-center font-redhat text-lg font-medium text-black opacity-0 transition-all duration-700 ease-in-out group-hover:h-full group-hover:translate-y-0 group-hover:opacity-100 md:text-sm lg:text-base">
"{slide.quote}"
</p>
</div>
</>
) : (
<img src={slide} alt={`Image`} className="aspect-auto rounded-xl" />
)}
</div>
)}
</div>
</div>
))}
</div>
</div>

{/* Shadowing for Images and Values */}
{purpose === "Images" ? <div className="absolute right-0 top-0 z-10 h-full w-16 bg-gradient-to-l from-white to-transparent" /> : null}
{purpose === "Values" ? <div className="absolute right-0 top-0 z-10 h-full w-16 bg-gradient-to-l from-black to-transparent" /> : null}

{/* Testimonials have arrows on sides while Values/Images have arrows at the bottom */}
{purpose === "Testimonials" ? (
<>
<div className="absolute right-0 top-0 z-10 mr-[8%] h-full w-16 bg-gradient-to-l from-white to-transparent" />
<NextButton onClick={onNextButtonClick} disabled={nextBtnDisabled} />
<NextButton onClick={onNextButtonClick} disabled={nextBtnDisabled} purpose={purpose} />
</>
) : (
<div className="mt-4 grid justify-center">
<div className="grid grid-cols-[1fr,1fr] items-center gap-2">
<PrevButton onClick={onPrevButtonClick} disabled={prevBtnDisabled} />
<NextButton onClick={onNextButtonClick} disabled={nextBtnDisabled} />
<PrevButton onClick={onPrevButtonClick} disabled={prevBtnDisabled} purpose={purpose} />
<NextButton onClick={onNextButtonClick} disabled={nextBtnDisabled} purpose={purpose} />
</div>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { cn } from "@/shared/utils";
import type { EmblaCarouselType } from "embla-carousel";
import type { ComponentPropsWithRef } from "react";
import React, { useCallback, useEffect, useState } from "react";
Expand Down Expand Up @@ -49,13 +50,19 @@ export const usePrevNextButtons = (
};
};

type PropType = ComponentPropsWithRef<"button">;
type PropType = ComponentPropsWithRef<"button"> & {
purpose: string;
};

export const PrevButton: React.FC<PropType> = (props) => {
const { children, ...restProps } = props;

return (
<button className="embla__button embla__button--prev text-white" type="button" {...restProps}>
<button
className={cn({ "text-white": props.purpose == "Values", "text-black": props.purpose != "Values" }, `embla__button embla__button--prev`)}
type="button"
{...restProps}
>
<svg className="h-[35%] w-[35%]" viewBox="0 0 532 532">
<path
fill="currentColor"
Expand All @@ -71,7 +78,11 @@ export const NextButton: React.FC<PropType> = (props) => {
const { children, ...restProps } = props;

return (
<button className="embla__button embla__button--next text-white" type="button" {...restProps}>
<button
className={cn({ "text-white": props.purpose == "Values", "text-black": props.purpose != "Values" }, `embla__button embla__button--next`)}
type="button"
{...restProps}
>
<svg className="h-[35%] w-[35%]" viewBox="0 0 532 532">
<path
fill="currentColor"
Expand Down
File renamed without changes.
159 changes: 0 additions & 159 deletions src/client/components/home/Carousel.tsx

This file was deleted.

Loading

0 comments on commit cf09f15

Please sign in to comment.