From be7a65ef8aa751bf15970a53e0e3c75e80b1c5b4 Mon Sep 17 00:00:00 2001 From: Andy Charlwood Date: Mon, 16 Feb 2026 11:02:32 +0000 Subject: [PATCH] feat: tune carousel autoplay for reduced motion --- src/components/tiles/ProjectsTile.tsx | 47 +++++++++++++++++---------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/src/components/tiles/ProjectsTile.tsx b/src/components/tiles/ProjectsTile.tsx index 4d946f9..ee1cef7 100644 --- a/src/components/tiles/ProjectsTile.tsx +++ b/src/components/tiles/ProjectsTile.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useMemo, useState } from 'react' +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import useEmblaCarousel from 'embla-carousel-react' import Autoplay from 'embla-carousel-autoplay' import { investigations } from '@/data/investigations' @@ -155,34 +155,47 @@ function ProjectItem({ project, slideBasis, onClick }: ProjectItemProps) { export function ProjectsTile() { const { openPanel } = useDetailPanel() + const autoplayPlugin = useRef( + Autoplay({ + delay: 3500, + playOnInit: false, + stopOnInteraction: false, + stopOnMouseEnter: true, + stopOnFocusIn: true, + }), + ) const [viewportWidth, setViewportWidth] = useState( typeof window !== 'undefined' ? window.innerWidth : 1200, ) - const [prefersReducedMotion, setPrefersReducedMotion] = useState(false) + const [prefersReducedMotion, setPrefersReducedMotion] = useState(() => + typeof window !== 'undefined' + ? window.matchMedia('(prefers-reduced-motion: reduce)').matches + : false, + ) - const [emblaRef] = useEmblaCarousel( + const [emblaRef, emblaApi] = useEmblaCarousel( { align: 'start', containScroll: 'trimSnaps', loop: true, dragFree: true, }, - useMemo( - () => - prefersReducedMotion - ? [] - : [ - Autoplay({ - delay: 3500, - stopOnInteraction: false, - stopOnMouseEnter: true, - stopOnFocusIn: true, - }), - ], - [prefersReducedMotion], - ), + useMemo(() => [autoplayPlugin.current], []), ) + useEffect(() => { + if (!emblaApi) { + return + } + + if (prefersReducedMotion) { + autoplayPlugin.current.stop() + return + } + + autoplayPlugin.current.play() + }, [emblaApi, prefersReducedMotion]) + useEffect(() => { if (typeof window === 'undefined') { return