Changes carousel auto scroll to pause when interaction occurs
This commit is contained in:
@@ -72,7 +72,7 @@ export function ChatWidget({ onAction }: ChatWidgetProps) {
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
if (!hasInteracted.current) setShowNudge(true)
|
||||
}, 12_000)
|
||||
}, 5_000)
|
||||
return () => clearTimeout(timer)
|
||||
}, [])
|
||||
|
||||
@@ -722,7 +722,7 @@ export function ChatWidget({ onAction }: ChatWidgetProps) {
|
||||
<motion.div
|
||||
initial={prefersReducedMotion ? { opacity: 1 } : { opacity: 0, y: 6 }}
|
||||
animate={{ opacity: 1, y: 0, transition: motionSafeTransition(0.25, 'easeOut') }}
|
||||
exit={prefersReducedMotion ? { opacity: 1 } : { opacity: 0, y: 4, transition: { duration: 0.2, ease: 'easeIn' } }}
|
||||
exit={{ opacity: 0, transition: { duration: 0 } }}
|
||||
className="fixed z-[101] right-4 md:right-6 pointer-events-none"
|
||||
style={{
|
||||
/* Position above button: button-bottom + button-height + gap */
|
||||
|
||||
@@ -539,9 +539,26 @@ function ContinuousScrollCarousel() {
|
||||
: false,
|
||||
)
|
||||
const resumeTimeoutRef = useRef<number>(0)
|
||||
const resumeTimestampRef = useRef<number | null>(null)
|
||||
const containerRef = useRef<HTMLDivElement>(null)
|
||||
const cardRefs = useRef<Map<number, HTMLDivElement>>(new Map())
|
||||
|
||||
const RESUME_DELAY_MS = 10000
|
||||
const RAMP_DURATION_MS = 2000
|
||||
|
||||
const pauseCarousel = useCallback(() => {
|
||||
isPausedRef.current = true
|
||||
window.clearTimeout(resumeTimeoutRef.current)
|
||||
}, [])
|
||||
|
||||
const scheduleResume = useCallback(() => {
|
||||
window.clearTimeout(resumeTimeoutRef.current)
|
||||
resumeTimeoutRef.current = window.setTimeout(() => {
|
||||
isPausedRef.current = false
|
||||
resumeTimestampRef.current = performance.now()
|
||||
}, RESUME_DELAY_MS)
|
||||
}, [])
|
||||
|
||||
const jumpByCards = useCallback((direction: 1 | -1) => {
|
||||
const trackEl = trackRef.current
|
||||
const firstSetEl = firstSetRef.current
|
||||
@@ -553,9 +570,7 @@ function ContinuousScrollCarousel() {
|
||||
const cardWidth = (viewportWidth - totalGap) / cardsPerView
|
||||
const jumpPx = cardWidth + gap
|
||||
|
||||
// Pause auto-scroll
|
||||
isPausedRef.current = true
|
||||
window.clearTimeout(resumeTimeoutRef.current)
|
||||
pauseCarousel()
|
||||
|
||||
// Apply CSS transition for smooth jump
|
||||
if (!prefersReducedMotion) {
|
||||
@@ -579,11 +594,8 @@ function ContinuousScrollCarousel() {
|
||||
trackEl.addEventListener('transitionend', transitionEnd, { once: true })
|
||||
}
|
||||
|
||||
// Resume auto-scroll after 6s
|
||||
resumeTimeoutRef.current = window.setTimeout(() => {
|
||||
isPausedRef.current = false
|
||||
}, 6000)
|
||||
}, [viewportWidth, prefersReducedMotion])
|
||||
scheduleResume()
|
||||
}, [viewportWidth, prefersReducedMotion, pauseCarousel, scheduleResume])
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
@@ -629,9 +641,19 @@ function ContinuousScrollCarousel() {
|
||||
const deltaSeconds = (timestamp - lastTime) / 1000
|
||||
lastTime = timestamp
|
||||
if (!isPausedRef.current) {
|
||||
let speedMultiplier = 1
|
||||
if (resumeTimestampRef.current !== null) {
|
||||
const elapsed = timestamp - resumeTimestampRef.current
|
||||
if (elapsed < RAMP_DURATION_MS) {
|
||||
const t = elapsed / RAMP_DURATION_MS
|
||||
speedMultiplier = 1 - Math.pow(1 - t, 2)
|
||||
} else {
|
||||
resumeTimestampRef.current = null
|
||||
}
|
||||
}
|
||||
const setWidth = firstSetEl.offsetWidth
|
||||
if (setWidth > 0) {
|
||||
offsetRef.current += speedPxPerSecond * deltaSeconds
|
||||
offsetRef.current += speedPxPerSecond * speedMultiplier * deltaSeconds
|
||||
if (offsetRef.current >= setWidth) offsetRef.current -= setWidth
|
||||
trackEl.style.transform = `translate3d(-${offsetRef.current}px, 0, 0)`
|
||||
}
|
||||
@@ -655,10 +677,6 @@ function ContinuousScrollCarousel() {
|
||||
return 214
|
||||
}, [viewportWidth])
|
||||
|
||||
const setPaused = (value: boolean) => {
|
||||
isPausedRef.current = value
|
||||
}
|
||||
|
||||
const handleArrowKey = useCallback((currentIndex: number, direction: -1 | 1) => {
|
||||
const nextIndex = (currentIndex + direction + investigations.length) % investigations.length
|
||||
cardRefs.current.get(nextIndex)?.focus()
|
||||
@@ -702,12 +720,12 @@ function ContinuousScrollCarousel() {
|
||||
<div
|
||||
ref={viewportRef}
|
||||
style={{ overflow: 'hidden' }}
|
||||
onMouseEnter={() => setPaused(true)}
|
||||
onMouseLeave={() => setPaused(false)}
|
||||
onFocusCapture={() => setPaused(true)}
|
||||
onMouseEnter={() => pauseCarousel()}
|
||||
onMouseLeave={() => scheduleResume()}
|
||||
onFocusCapture={() => pauseCarousel()}
|
||||
onBlurCapture={(event) => {
|
||||
if (!event.currentTarget.contains(event.relatedTarget as Node | null)) {
|
||||
setPaused(false)
|
||||
scheduleResume()
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user