feat(ui): add autoplay to testimonials and display author initials avatar
This commit is contained in:
@@ -1,11 +1,27 @@
|
||||
'use client'
|
||||
import React, { useState } from 'react'
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import type { Page } from '../../payload-types'
|
||||
|
||||
type Props = Extract<NonNullable<Page['layout']>[0], { blockType: 'testimonials' }>
|
||||
|
||||
export const TestimonialsBlock: React.FC<Props> = ({ title, testimonials }) => {
|
||||
const [currentIndex, setCurrentIndex] = useState(0)
|
||||
const [lastActionTime, setLastActionTime] = useState(Date.now())
|
||||
|
||||
useEffect(() => {
|
||||
if (!testimonials || testimonials.length <= 1) return
|
||||
|
||||
const interval = setInterval(() => {
|
||||
setCurrentIndex((prev) => (prev + 1) % testimonials.length)
|
||||
}, 7500)
|
||||
|
||||
return () => clearInterval(interval)
|
||||
}, [testimonials, lastActionTime])
|
||||
|
||||
const handleDotClick = (index: number) => {
|
||||
setCurrentIndex(index)
|
||||
setLastActionTime(Date.now())
|
||||
}
|
||||
|
||||
if (!testimonials || testimonials.length === 0) return null
|
||||
|
||||
@@ -21,7 +37,9 @@ export const TestimonialsBlock: React.FC<Props> = ({ title, testimonials }) => {
|
||||
</div>
|
||||
|
||||
<div className="relative min-h-[300px] sm:min-h-[240px]">
|
||||
{testimonials.map((t: NonNullable<Props['testimonials']>[0], index: number) => (
|
||||
{testimonials.map((t: NonNullable<Props['testimonials']>[0], index: number) => {
|
||||
const initial = t.author ? t.author.charAt(0).toUpperCase() : ''
|
||||
return (
|
||||
<div
|
||||
key={t.id || index}
|
||||
className={`absolute inset-0 flex flex-col items-start justify-start transition-opacity duration-1000 ease-in-out ${
|
||||
@@ -32,14 +50,20 @@ export const TestimonialsBlock: React.FC<Props> = ({ title, testimonials }) => {
|
||||
{t.quote}
|
||||
</p>
|
||||
|
||||
<div className="flex items-center gap-6">
|
||||
<div className="hidden sm:block w-12 h-px bg-accent/60" />
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-12 h-px bg-accent/60" />
|
||||
<div className="w-12 h-12 rounded-full bg-accent text-background font-heading flex items-center justify-center text-xl sm:text-2xl font-bold shrink-0">
|
||||
{initial}
|
||||
</div>
|
||||
<p className="font-heading font-bold text-lg sm:text-xl text-foreground/80 uppercase tracking-wide">
|
||||
{t.author}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
{testimonials.length > 1 && (
|
||||
@@ -47,7 +71,7 @@ export const TestimonialsBlock: React.FC<Props> = ({ title, testimonials }) => {
|
||||
{testimonials.map((_, index) => (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() => setCurrentIndex(index)}
|
||||
onClick={() => handleDotClick(index)}
|
||||
className={`w-2 h-2 transition-all ${
|
||||
index === currentIndex ? 'bg-accent w-8' : 'bg-border hover:bg-foreground/30'
|
||||
}`}
|
||||
|
||||
Reference in New Issue
Block a user