forked from UKSOURCE/ipv6
104 lines
3.4 KiB
TypeScript
104 lines
3.4 KiB
TypeScript
"use client";
|
|
|
|
// Tên file chính xác trong public/assets/img/carousel/
|
|
const ROW_1 = [
|
|
// { name: "IEAS", file: "ieas.png" },
|
|
{ name: "NVIDIA", file: "Nvidia_logo.svg.png" },
|
|
{ name: "Maxis", file: "Maxis-logo.png" },
|
|
{ name: "Singtel", file: "Singtel_logo.svg.png" },
|
|
{ name: "NIDA", file: "nida.png" },
|
|
{ name: "VNNIC", file: "vnnic.png" },
|
|
{ name: "Netflix", file: "Logonetflix.png" },
|
|
{ name: "Microsoft",file: "Microsoft-Logo.png" },
|
|
{ name: "Alibaba", file: "Alibaba-Logo.png" },
|
|
];
|
|
|
|
const ROW_2 = [
|
|
{ name: "Tencent", file: "tencent.png" },
|
|
{ name: "AirTrunk", file: "airtrunk.png" },
|
|
{ name: "Celcomdigi",file: "celcomdigi.png" },
|
|
{ name: "Grab", file: "grab.png" },
|
|
{ name: "Logo 1", file: "logo_transparent.png" },
|
|
{ name: "Logo 2", file: "Equinix_logo.svg.png" },
|
|
{ name: "Logo 3", file: "XL_Axiata-Logo.wine.png" },
|
|
{ name: "Logo 4", file: "Huawei_Standard_logo.svg.png" },
|
|
];
|
|
|
|
function CarouselRow({
|
|
items,
|
|
base,
|
|
reverse = false,
|
|
}: {
|
|
items: { name: string; file: string }[];
|
|
base: string;
|
|
reverse?: boolean;
|
|
}) {
|
|
// Lặp 3 lần để đảm bảo không bao giờ thấy khoảng trống
|
|
const tripled = [...items, ...items, ...items];
|
|
// Mỗi item: w=150px, gap=20px → 1 set = items.length * 170 - 20
|
|
const setWidth = items.length * 150 + (items.length - 1) * 20;
|
|
|
|
return (
|
|
<div className="overflow-hidden w-full">
|
|
<div
|
|
className="flex gap-5 w-max"
|
|
style={{
|
|
animation: `${reverse ? "scroll-reverse" : "scroll-fwd"} ${items.length * 3}s linear infinite`,
|
|
["--set-width" as string]: `${setWidth}px`,
|
|
}}
|
|
>
|
|
{tripled.map((item, i) => (
|
|
<div
|
|
key={`${item.file}-${i}`}
|
|
className="flex items-center justify-center shrink-0 w-[150px] h-[76px] rounded-xl border border-white/10 hover:border-primary/40 transition-colors duration-300 overflow-hidden"
|
|
style={{ background: "rgba(255,255,255,0.82)" }}
|
|
>
|
|
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
<img
|
|
src={`${base}/assets/img/carousel/${item.file}`}
|
|
alt={item.name}
|
|
style={{
|
|
maxHeight: 48,
|
|
maxWidth: 118,
|
|
width: "auto",
|
|
height: "auto",
|
|
objectFit: "contain",
|
|
mixBlendMode: "multiply",
|
|
filter: "contrast(1.05)",
|
|
}}
|
|
/>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default function PartnersCarousel({
|
|
eyebrow = "Partners & Sponsors",
|
|
title = "Trusted by Industry Leaders",
|
|
}: {
|
|
eyebrow?: string;
|
|
title?: string;
|
|
}) {
|
|
const base = process.env.NEXT_PUBLIC_BASE_PATH || "";
|
|
|
|
return (
|
|
<section className="w-full py-16 lg:py-24 overflow-hidden border-t border-white/5">
|
|
<div className="mb-10 px-[var(--spacing-gutter)] max-w-hd mx-auto">
|
|
<p className="text-primary font-[var(--font-label-caps)] text-xs tracking-[0.3em] uppercase mb-3">
|
|
{eyebrow}
|
|
</p>
|
|
<h2 className="text-on-surface font-[var(--font-display-lg)] text-2xl lg:text-4xl font-bold">
|
|
{title}
|
|
</h2>
|
|
</div>
|
|
|
|
<div className="flex flex-col gap-5">
|
|
<CarouselRow items={ROW_1} base={base} reverse={false} />
|
|
<CarouselRow items={ROW_2} base={base} reverse={true} />
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|