Template
35 lines
1.7 KiB
TypeScript
35 lines
1.7 KiB
TypeScript
import type { CSSProperties } from 'react';
|
|
|
|
export type LogoMarqueeProps = {
|
|
heading?: string;
|
|
logos?: Array<{ name: string; imageUrl?: string }>;
|
|
speed?: 'slow' | 'normal' | 'fast';
|
|
direction?: 'left' | 'right';
|
|
pauseOnHover?: 'yes' | 'no';
|
|
};
|
|
|
|
export default function LogoMarquee({ heading = '', logos = [], speed = 'normal', direction = 'left', pauseOnHover = 'yes' }: LogoMarqueeProps) {
|
|
const duration = speed === 'slow' ? '42s' : speed === 'fast' ? '18s' : '28s';
|
|
const items = [...logos, ...logos];
|
|
|
|
return (
|
|
<section className="bg-background py-12 sm:py-14">
|
|
<div className="section-shell">
|
|
{heading && <p className="text-center text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground">{heading}</p>}
|
|
<div className="mt-8 overflow-hidden [mask-image:linear-gradient(to_right,transparent,black_12%,black_88%,transparent)]">
|
|
<div
|
|
className={`animate-marquee flex w-max items-center ${direction === 'right' ? 'marquee-reverse' : ''} ${pauseOnHover === 'yes' ? 'marquee-pause' : ''}`}
|
|
style={{ '--marquee-duration': duration } as CSSProperties}
|
|
>
|
|
{items.map((logo, index) => (
|
|
<div key={`${logo.name}-${index}`} aria-hidden={index >= logos.length} className="mx-8 flex h-10 min-w-32 items-center justify-center sm:mx-12">
|
|
{logo.imageUrl ? <img src={logo.imageUrl} alt={logo.name} className="max-h-7 max-w-32 object-contain opacity-55 grayscale dark:invert" /> : <span className="text-lg font-semibold tracking-[-0.03em] text-muted-foreground/80">{logo.name}</span>}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|