1
1
"use client"
2
2
3
3
import { 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"
6
6
import useMeasure from "react-use-measure"
7
7
8
8
export interface MarqueeProps extends React . HTMLAttributes < HTMLElement > {
@@ -29,13 +29,23 @@ export function Marquee({
29
29
separator,
30
30
...rest
31
31
} : MarqueeProps ) {
32
+ const shouldReduceMotion = useReducedMotion ( )
32
33
const [ currentSpeed , setCurrentSpeed ] = useState ( speed )
33
34
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 )
35
40
const [ isTransitioning , setIsTransitioning ] = useState ( false )
36
41
const [ key , setKey ] = useState ( 0 )
37
42
38
43
useEffect ( ( ) => {
44
+ if ( shouldReduceMotion ) {
45
+ setCurrentSpeed ( 0 )
46
+ return
47
+ }
48
+
39
49
let controls
40
50
const size = direction === "horizontal" ? width : height
41
51
const contentSize = size + gap
@@ -81,6 +91,7 @@ export function Marquee({
81
91
isTransitioning ,
82
92
direction ,
83
93
reverse ,
94
+ shouldReduceMotion ,
84
95
] )
85
96
86
97
const hoverProps =
@@ -135,6 +146,7 @@ export function Marquee({
135
146
: { }
136
147
137
148
const multiples = 2
149
+
138
150
return (
139
151
< div className = { clsx ( "overflow-hidden" , className ) } { ...rest } >
140
152
< motion . div
@@ -155,7 +167,7 @@ export function Marquee({
155
167
hoverProps . onPointerUp ?.( event )
156
168
} }
157
169
>
158
- { Array . from ( { length : 2 } ) . map ( ( _ , i ) => (
170
+ { Array . from ( { length : multiples } ) . map ( ( _ , i ) => (
159
171
< Fragment key = { i } >
160
172
{ children }
161
173
{ i < multiples - 1 && separator }
@@ -165,3 +177,11 @@ export function Marquee({
165
177
</ div >
166
178
)
167
179
}
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