Files
oms-website-nextjs/app/(website)/_components/ClientLogosSection.tsx

117 lines
4.1 KiB
TypeScript

// components/ClientLogosSection.tsx
import React from "react";
import Image from "next/image";
// Define structure for client data - focusing on logos now
type Client = {
name: string;
logoUrl: string; // Expecting actual logo URLs now
};
type ClientLogosSectionProps = {
title: string;
description?: string;
clients: Client[];
/** Control animation speed (lower number = faster). Default: 40s */
speed?: number;
/** Size of the square background container in pixels. Default: 120 */
squareSize?: number;
};
const ClientLogosSection: React.FC<ClientLogosSectionProps> = ({
title,
description,
clients = [], // Default to empty array
speed = 40, //Default speed in seconds for one full cycle
squareSize = 120, // Default size for the square container (e.g., 120px)
}) => {
// Need at least one client to render the marquee
if (clients.length === 0) {
return null; // Or render a placeholder message if preferred
}
// Duplicate the clients for a seamless loop effect
const extendedClients = [...clients, ...clients];
const squareDim = `${squareSize}px`; // Convert size to string for inline style
const padding = Math.round(squareSize / 6); // Calculate padding based on size (adjust divisor as needed)
const paddingDim = `${padding}px`;
return (
<section className="py-16 md:py-20 bg-background overflow-hidden">
<div className="container mx-auto px-4 sm:px-6 lg:px-8 text-center">
<h2 className="text-3xl md:text-4xl font-bold mb-12 text-foreground">
{title}
</h2>
</div>
{/* Marquee container - group allows pausing animation on hover */}
<div className="relative w-full overflow-hidden group">
{/* Inner container that will animate */}
<div
className="flex flex-nowrap animate-marquee-continuous"
style={{ animationDuration: `${speed}s` }}
>
{extendedClients.map((client, index) => (
<div
key={`${client.name}-${index}`}
className="flex-shrink-0 mx-12 md:mx-16 py-4"
>
{/* Square Background Container */}
<div
title={client.name}
className="
relative flex items-center justify-center
bg-muted/30 dark:bg-muted/20
rounded-lg shadow-sm
overflow-hidden
grayscale hover:grayscale-0
opacity-70 hover:opacity-100
transition-all duration-300 ease-in-out
cursor-pointer
"
style={{
width: squareDim,
height: squareDim,
padding: paddingDim, // Add padding inside the square
}}
>
<Image
src={client.logoUrl}
alt={`${client.name} Logo`}
layout="fill" // Let image fill the relative container
objectFit="contain" // Maintain aspect ratio within the container
/>
</div>
</div>
))}
</div>
{/* Optional: Add fade effect at the edges */}
<div className="absolute inset-y-0 left-0 w-16 md:w-24 bg-gradient-to-r from-background to-transparent pointer-events-none z-10"></div>
<div className="absolute inset-y-0 right-0 w-16 md:w-24 bg-gradient-to-l from-background to-transparent pointer-events-none z-10"></div>
</div>
{description && (
<div className="container mx-auto px-4 sm:px-6 lg:px-8 text-center">
<p className="mt-10 text-muted-foreground italic text-sm">
{description}
</p>
</div>
)}
</section>
);
};
export const defaultClients: Client[] = [
{ name: "ABSA", logoUrl: "/images/absa.png" },
{ name: "SYBRIN", logoUrl: "/images/sybrin.svg" },
{ name: "SASOL", logoUrl: "/images/sasol.png" },
{ name: "JACARANDA", logoUrl: "/images/jacaranda.png" },
{ name: "SALESFORCE", logoUrl: "/images/salesforce.png" },
{ name: "BCX", logoUrl: "/images/bcx.png" },
{ name: "TOYOTA", logoUrl: "/images/toyota-logo.png" },
];
export default ClientLogosSection;