11"use client"
22
33import { clsx } from "clsx"
4- import { useMotionValue , animate , motion } from "motion/react"
5- import { useState , useEffect , Fragment } from "react"
4+ import { useMotionValue , animate , motion , useReducedMotion } from "motion/react"
5+ import { useState , useEffect , Fragment , useId } from "react"
66import useMeasure from "react-use-measure"
77
88export interface MarqueeProps extends React . HTMLAttributes < HTMLElement > {
@@ -29,13 +29,23 @@ export function Marquee({
2929 separator,
3030 ...rest
3131} : MarqueeProps ) {
32+ const shouldReduceMotion = useReducedMotion ( )
3233 const [ currentSpeed , setCurrentSpeed ] = useState ( speed )
3334 const [ ref , { width, height } ] = useMeasure ( )
34- const translation = useMotionValue ( 0 )
35+
36+ // ensure the marquees don't start in the same place.
37+ const initialShiftPx = useSomeValue ( ) * - 64
38+
39+ const translation = useMotionValue ( initialShiftPx )
3540 const [ isTransitioning , setIsTransitioning ] = useState ( false )
3641 const [ key , setKey ] = useState ( 0 )
3742
3843 useEffect ( ( ) => {
44+ if ( shouldReduceMotion ) {
45+ setCurrentSpeed ( 0 )
46+ return
47+ }
48+
3949 let controls
4050 const size = direction === "horizontal" ? width : height
4151 const contentSize = size + gap
@@ -81,6 +91,7 @@ export function Marquee({
8191 isTransitioning ,
8292 direction ,
8393 reverse ,
94+ shouldReduceMotion ,
8495 ] )
8596
8697 const hoverProps =
@@ -135,6 +146,7 @@ export function Marquee({
135146 : { }
136147
137148 const multiples = 2
149+
138150 return (
139151 < div className = { clsx ( "overflow-hidden" , className ) } { ...rest } >
140152 < motion . div
@@ -155,7 +167,7 @@ export function Marquee({
155167 hoverProps . onPointerUp ?.( event )
156168 } }
157169 >
158- { Array . from ( { length : 2 } ) . map ( ( _ , i ) => (
170+ { Array . from ( { length : multiples } ) . map ( ( _ , i ) => (
159171 < Fragment key = { i } >
160172 { children }
161173 { i < multiples - 1 && separator }
@@ -165,3 +177,11 @@ export function Marquee({
165177 </ div >
166178 )
167179}
180+
181+ function useSomeValue ( ) {
182+ const id = useId ( )
183+ const num =
184+ id . split ( "" ) . reduce ( ( acc , char ) => acc + char . charCodeAt ( 0 ) , 0 ) - 950
185+
186+ return Math . abs ( Math . sin ( num ) )
187+ }
0 commit comments