Files
web/apps/scandic-web/components/MarqueeText/index.tsx
Erik Tiekstra fa10abbe78 fix(BOOK-496): Slowed down the MarqueeText component animation
Approved-by: Matilda Landström
2025-11-04 10:29:20 +00:00

93 lines
2.4 KiB
TypeScript

"use client"
import { cx } from "class-variance-authority"
import { useEffect, useRef, useState } from "react"
import styles from "./marqueeText.module.css"
interface MarqueeTextProps
extends React.PropsWithChildren<React.HTMLAttributes<HTMLDivElement>> {
backgroundColor: string
textWrapperClassName?: string
}
export function MarqueeText({
backgroundColor,
children,
className,
textWrapperClassName,
...props
}: MarqueeTextProps) {
const textContainerRef = useRef<HTMLDivElement>(null)
const [dimensions, setDimensions] = useState({
containerWidth: 0,
contentWidth: 0,
isOverflowing: false,
})
useEffect(() => {
const element = textContainerRef.current
const parentElement = element?.parentElement
if (!parentElement) {
return
}
const resizeObserver = new ResizeObserver(() => {
const containerWidth = element.clientWidth
const contentWidth = element.scrollWidth
const isOverflowing = contentWidth > containerWidth
setDimensions({
containerWidth,
contentWidth,
isOverflowing,
})
if (isOverflowing && containerWidth > 0) {
const scrollDistance = contentWidth - containerWidth
parentElement.style.setProperty(
"--scroll-distance",
`${scrollDistance}px`
)
// Calculate dynamic animation duration based on scroll distance
// This is done to avoid long scrolling durations for small distances and vice versa
// Base formula: minimum 4000ms, add 60ms per pixel of scroll distance. The duration
// includes start and end pauses.
const baseDuration = 4000
const durationPerPixel = 60
const calculatedDuration =
baseDuration + scrollDistance * durationPerPixel
parentElement.style.setProperty(
"--animation-duration",
`${calculatedDuration}ms`
)
}
})
resizeObserver.observe(element)
return () => resizeObserver.disconnect()
}, [])
return (
<div
className={cx(styles.marqueeText, className)}
style={
{ "--marquee-background-color": backgroundColor } as React.CSSProperties
}
{...props}
>
<div
ref={textContainerRef}
className={cx(styles.textWrapper, textWrapperClassName, {
[styles.overflowing]: dimensions.isOverflowing,
})}
>
{children}
</div>
</div>
)
}