show testimonial previews

This commit is contained in:
Yisroel Baum 2026-06-06 22:33:40 +03:00
parent 3c72cd296e
commit b88fe99b38
Signed by: yisroelbaum
GPG key ID: 0FA60884F75520A9

View file

@ -23,6 +23,8 @@ interface Testimonial {
quote: string quote: string
} }
type TestimonialPosition = 'active' | 'previous' | 'next' | 'hidden'
const testimonials: Testimonial[] = [ const testimonials: Testimonial[] = [
{ {
name: 'Nathaniel M', name: 'Nathaniel M',
@ -45,12 +47,62 @@ const testimonials: Testimonial[] = [
const testimonialIndex = ref(0) const testimonialIndex = ref(0)
function previousTestimonialIndex(): number {
if (testimonialIndex.value === 0) {
return testimonials.length - 1
}
return testimonialIndex.value - 1
}
function nextTestimonialIndex(): number {
return (testimonialIndex.value + 1) % testimonials.length
}
function testimonialPosition(index: number): TestimonialPosition {
if (index === testimonialIndex.value) {
return 'active'
}
if (index === previousTestimonialIndex()) {
return 'previous'
}
if (index === nextTestimonialIndex()) {
return 'next'
}
return 'hidden'
}
function testimonialDataCy(index: number): string {
const position = testimonialPosition(index)
if (position === 'active') {
return 'testimonial-active'
}
if (position === 'previous') {
return 'testimonial-previous-preview'
}
if (position === 'next') {
return 'testimonial-next-preview'
}
return 'testimonial-hidden'
}
function testimonialClass(index: number): string {
return `testimonials__card--${testimonialPosition(index)}`
}
function nextTestimonial(): void { function nextTestimonial(): void {
testimonialIndex.value = (testimonialIndex.value + 1) % testimonials.length testimonialIndex.value = nextTestimonialIndex()
} }
function previousTestimonial(): void { function previousTestimonial(): void {
testimonialIndex.value = (testimonialIndex.value - 1 + testimonials.length) % testimonials.length testimonialIndex.value = previousTestimonialIndex()
} }
const newsletterFullName = ref('') const newsletterFullName = ref('')
@ -229,16 +281,14 @@ const projects: Project[] = [
<section class="testimonials" data-cy="testimonials"> <section class="testimonials" data-cy="testimonials">
<div class="testimonials__inner"> <div class="testimonials__inner">
<h2 class="testimonials__heading">What People Are Saying</h2> <h2 class="testimonials__heading">What People Are Saying</h2>
<div class="testimonials__stage"> <div class="testimonials__stage" data-cy="testimonials-stage">
<div <div
v-for="(testimonial, index) in testimonials" v-for="(testimonial, index) in testimonials"
:key="testimonial.name" :key="testimonial.name"
class="testimonials__card" class="testimonials__card"
:class="{ :class="testimonialClass(index)"
'testimonials__card--active': index === testimonialIndex, :data-cy="testimonialDataCy(index)"
}" :aria-hidden="testimonialPosition(index) !== 'active'"
:data-cy="index === testimonialIndex ? 'testimonial-active' : 'testimonial-side'"
:aria-hidden="index !== testimonialIndex"
> >
<h3 class="testimonials__name">{{ testimonial.name }}</h3> <h3 class="testimonials__name">{{ testimonial.name }}</h3>
<p class="testimonials__quote">&ldquo;{{ testimonial.quote }}&rdquo;</p> <p class="testimonials__quote">&ldquo;{{ testimonial.quote }}&rdquo;</p>
@ -666,7 +716,10 @@ const projects: Project[] = [
.testimonials__stage { .testimonials__stage {
position: relative; position: relative;
width: min(100%, 960px);
margin: 0 auto;
min-height: 220px; min-height: 220px;
overflow: hidden;
} }
.testimonials__card { .testimonials__card {
@ -674,18 +727,42 @@ const projects: Project[] = [
border-radius: 14px; border-radius: 14px;
padding: 2rem; padding: 2rem;
text-align: left; text-align: left;
width: 50%;
max-width: 480px; max-width: 480px;
margin: 0 auto;
opacity: 0; opacity: 0;
visibility: hidden; visibility: hidden;
position: absolute; position: absolute;
inset: 0; top: 0;
transition: opacity 0.3s ease; left: 50%;
margin: 0;
box-sizing: border-box;
pointer-events: none;
transform: translateX(-50%);
transition:
opacity 0.3s ease,
transform 0.3s ease;
} }
.testimonials__card--active { .testimonials__card--active {
opacity: 1; opacity: 1;
visibility: visible; visibility: visible;
z-index: 2;
transform: translateX(-50%);
}
.testimonials__card--previous,
.testimonials__card--next {
opacity: 0.35;
visibility: visible;
z-index: 1;
}
.testimonials__card--previous {
transform: translateX(-150%);
}
.testimonials__card--next {
transform: translateX(50%);
} }
.testimonials__name { .testimonials__name {