82 lines
2.0 KiB
TypeScript
82 lines
2.0 KiB
TypeScript
import React, { useState } from "react";
|
|
import { Color } from "utils/Color";
|
|
|
|
import styles from "./QuotationCarousel.module.css";
|
|
|
|
interface QuotationCarouselProps {
|
|
data: string[];
|
|
}
|
|
|
|
interface QuotationCardProps {
|
|
quote: string;
|
|
isActive?: boolean;
|
|
}
|
|
|
|
interface CarouselButtonProps {
|
|
onClick: () => void;
|
|
isPrevious?: boolean;
|
|
}
|
|
|
|
export function QuotationCarousel(props: QuotationCarouselProps) {
|
|
const { data } = props;
|
|
|
|
const [activeIdx, setActiveIdx] = useState(0);
|
|
|
|
function showNextCard() {
|
|
setActiveIdx((activeIdx + 1) % data.length);
|
|
}
|
|
|
|
function showPreviousCard() {
|
|
setActiveIdx((activeIdx - 1 + data.length) % data.length);
|
|
}
|
|
|
|
return (
|
|
<section className={styles.carousel}>
|
|
<CarouselButton onClick={showPreviousCard} isPrevious />
|
|
{data.map((quote, idx) => {
|
|
return (
|
|
<QuotationCard key={idx} quote={quote} isActive={idx === activeIdx} />
|
|
);
|
|
})}
|
|
<CarouselButton onClick={showNextCard} />
|
|
</section>
|
|
);
|
|
}
|
|
|
|
function QuotationCard({ quote, isActive }: QuotationCardProps) {
|
|
const className = isActive ? `${styles.active} ${styles.card}` : styles.card;
|
|
|
|
return (
|
|
<div className={className}>
|
|
{/* TODO: improve quotation mark alignment - maybe use images? */}
|
|
<div className={styles.quotationMark}>“</div>
|
|
<p>{quote}</p>
|
|
<div className={`${styles.right} ${styles.quotationMark}`}>”</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function CarouselButton({ isPrevious, onClick }: CarouselButtonProps) {
|
|
return (
|
|
<button className={styles.carouselButton} onClick={onClick}>
|
|
<svg
|
|
className={
|
|
isPrevious ? `${styles.previous} ${styles.arrow}` : styles.arrow
|
|
}
|
|
width="39"
|
|
height="72"
|
|
viewBox="0 0 39 72"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<path
|
|
d="M4 4L34.4206 35.804C35.2926 36.7157 35.2597 38.1619 34.3471 39.0329L4 68"
|
|
stroke={Color.primaryAccentLighter}
|
|
strokeWidth="4"
|
|
strokeLinecap="round"
|
|
/>
|
|
</svg>
|
|
</button>
|
|
);
|
|
}
|