fix(testimonials): group dots by pages on desktop and scroll by two items
This commit is contained in:
@@ -46,7 +46,8 @@ export const TestimonialsCarousel: React.FC<CarouselProps> = ({ title, items })
|
||||
let minDiff = Infinity
|
||||
|
||||
children.forEach((child, index) => {
|
||||
const diff = Math.abs(child.offsetLeft - scrollLeft)
|
||||
const childRelativeLeft = child.offsetLeft - containerRef.current!.offsetLeft
|
||||
const diff = Math.abs(childRelativeLeft - scrollLeft)
|
||||
if (diff < minDiff) {
|
||||
minDiff = diff
|
||||
closestIndex = index
|
||||
@@ -76,23 +77,29 @@ export const TestimonialsCarousel: React.FC<CarouselProps> = ({ title, items })
|
||||
const child = children[index] as HTMLElement
|
||||
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches
|
||||
|
||||
const targetLeft = child.offsetLeft - containerRef.current.offsetLeft
|
||||
|
||||
containerRef.current.scrollTo({
|
||||
left: child.offsetLeft,
|
||||
left: targetLeft,
|
||||
behavior: prefersReducedMotion ? 'auto' : 'smooth'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const scrollPrev = () => {
|
||||
scrollTo(Math.max(activeIndex - 1, 0))
|
||||
const step = window.innerWidth >= 768 ? 2 : 1
|
||||
scrollTo(Math.max(activeIndex - step, 0))
|
||||
}
|
||||
|
||||
const scrollNext = () => {
|
||||
scrollTo(Math.min(activeIndex + 1, items.length - 1))
|
||||
const step = window.innerWidth >= 768 ? 2 : 1
|
||||
scrollTo(Math.min(activeIndex + step, items.length - 1))
|
||||
}
|
||||
|
||||
if (!items || items.length === 0) return null
|
||||
|
||||
const desktopPages = Math.ceil(items.length / 2)
|
||||
|
||||
return (
|
||||
<section className="relative py-24 md:py-40 bg-background overflow-x-hidden max-w-[100vw]">
|
||||
<div className="container-premium relative z-10">
|
||||
@@ -117,7 +124,7 @@ export const TestimonialsCarousel: React.FC<CarouselProps> = ({ title, items })
|
||||
</button>
|
||||
<button
|
||||
onClick={scrollNext}
|
||||
disabled={activeIndex >= items.length - 1} // Na desktopie widać po 2 karty, wiec to mozna ulepszyc, ale zostawmy proste
|
||||
disabled={activeIndex >= items.length - 1 || (activeIndex === items.length - 2 && items.length % 2 === 0)}
|
||||
aria-label="Następna opinia"
|
||||
className="w-12 h-12 rounded-full border border-border flex items-center justify-center text-foreground hover:bg-accent hover:text-background hover:border-accent disabled:opacity-30 disabled:hover:bg-transparent disabled:hover:text-foreground disabled:hover:border-border transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent"
|
||||
>
|
||||
@@ -175,8 +182,8 @@ export const TestimonialsCarousel: React.FC<CarouselProps> = ({ title, items })
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
{/* Kropki nawigacji (Mobile + Desktop) */}
|
||||
<div className="flex justify-center items-center gap-3 mt-8">
|
||||
{/* Kropki nawigacji (Mobile - pojedyncze karty) */}
|
||||
<div className="flex md:hidden justify-center items-center gap-3 mt-8">
|
||||
{items.map((_, index) => (
|
||||
<button
|
||||
key={index}
|
||||
@@ -191,6 +198,26 @@ export const TestimonialsCarousel: React.FC<CarouselProps> = ({ title, items })
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Kropki nawigacji (Desktop - grupowane po 2 karty) */}
|
||||
<div className="hidden md:flex justify-center items-center gap-3 mt-8">
|
||||
{Array.from({ length: desktopPages }).map((_, pageIndex) => {
|
||||
const isActive = Math.floor(activeIndex / 2) === pageIndex
|
||||
return (
|
||||
<button
|
||||
key={pageIndex}
|
||||
onClick={() => scrollTo(pageIndex * 2)}
|
||||
aria-label={`Przejdź do strony ${pageIndex + 1}`}
|
||||
aria-current={isActive ? 'true' : 'false'}
|
||||
className={`w-3 h-3 rounded-full transition-all duration-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent ${
|
||||
isActive
|
||||
? 'bg-accent scale-100'
|
||||
: 'bg-border hover:bg-accent/50 scale-75'
|
||||
}`}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user