Files
songs2vid/components/FooterBadgeMarquee.tsx
T

63 lines
1.5 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import { BadgeEmbed } from "@/components/BadgeEmbed";
export type PublicFooterBadge = {
id: string;
name: string;
embedHtml: string | null;
imageUrl: string | null;
linkUrl: string | null;
sortOrder: number;
};
type Props = {
initialBadges?: PublicFooterBadge[];
};
export function FooterBadgeMarquee({ initialBadges = [] }: Props) {
const [badges, setBadges] = useState<PublicFooterBadge[]>(initialBadges);
useEffect(() => {
let cancelled = false;
fetch("/api/badges")
.then(async (res) => {
if (!res.ok) return;
const data = await res.json();
if (!cancelled && Array.isArray(data.badges)) {
setBadges(data.badges);
}
})
.catch(() => {});
return () => {
cancelled = true;
};
}, []);
if (badges.length === 0) return null;
// Duplicate track for seamless infinite scroll
const loop = [...badges, ...badges];
const durationSec = Math.max(18, badges.length * 10);
return (
<div className="badge-marquee mb-12" aria-label="Featured on">
<div
className="badge-marquee-track"
style={{ ["--badge-marquee-duration" as string]: `${durationSec}s` }}
>
{loop.map((badge, index) => (
<div
key={`${badge.id}-${index}`}
className="badge-marquee-item"
aria-hidden={index >= badges.length ? true : undefined}
>
<BadgeEmbed badge={badge} />
</div>
))}
</div>
</div>
);
}