ClientLogosScroll Social Proof
Dubbele scrollende logo rij voor klanten (marquee-stijl).
src/components/social-proof/ClientLogosScroll.astro
---
/**
* ClientLogosScroll
* Dubbele scrollende logo rij (marquee-stijl) voor klanten/partners.
*/
interface Props {
eyebrow?: string;
logos: { name: string; src?: string }[];
speed?: 'slow' | 'normal' | 'fast';
bg?: 'white' | 'light' | 'dark';
}
const { eyebrow = 'Vertrouwd door', logos, speed = 'normal', bg = 'white' } = Astro.props;
const duration = speed === 'slow' ? '40s' : speed === 'fast' ? '15s' : '25s';
---
<section class={`cls cls--${bg}`}>
<div class="cls-inner">
{eyebrow && <p class="cls-eyebrow">{eyebrow}</p>}
<div class="cls-track-wrap">
<div class="cls-track" style={`animation-duration: ${duration}`}>
{[...logos, ...logos].map((l) => (
<div class="cls-logo">
{l.src
? <img src={l.src} alt={l.name} class="cls-img" />
: <span class="cls-name">{l.name}</span>
}
</div>
))}
</div>
</div>
</div>
</section>
<style>
.cls { padding: 3.5rem 0; overflow: hidden; }
.cls--white { background: #fff; border-top: 1px solid #e5e7eb; border-bottom: 1px solid #e5e7eb; }
.cls--light { background: #f8fafc; border-top: 1px solid #e5e7eb; border-bottom: 1px solid #e5e7eb; }
.cls--dark { background: #0a0a0a; }
.cls-inner { }
.cls-eyebrow { text-align: center; font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; margin: 0 0 1.75rem; }
.cls--white .cls-eyebrow, .cls--light .cls-eyebrow { color: #9ca3af; }
.cls--dark .cls-eyebrow { color: rgba(255,255,255,0.3); }
.cls-track-wrap { position: relative; }
.cls-track-wrap::before, .cls-track-wrap::after { content: ''; position: absolute; top: 0; bottom: 0; width: 120px; z-index: 2; pointer-events: none; }
.cls--white .cls-track-wrap::before, .cls--light .cls-track-wrap::before { background: linear-gradient(90deg, #fff, transparent); }
.cls--white .cls-track-wrap::after, .cls--light .cls-track-wrap::after { background: linear-gradient(-90deg, #fff, transparent); right: 0; }
.cls--dark .cls-track-wrap::before { background: linear-gradient(90deg, #0a0a0a, transparent); }
.cls--dark .cls-track-wrap::after { background: linear-gradient(-90deg, #0a0a0a, transparent); right: 0; }
.cls--light .cls-track-wrap::before { background: linear-gradient(90deg, #f8fafc, transparent); }
.cls--light .cls-track-wrap::after { background: linear-gradient(-90deg, #f8fafc, transparent); right: 0; }
.cls-track { display: flex; gap: 3rem; align-items: center; width: max-content; animation: cls-scroll linear infinite; }
@keyframes cls-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.cls-logo { flex-shrink: 0; display: flex; align-items: center; justify-content: center; padding: 0.5rem 1rem; }
.cls-img { height: 28px; width: auto; opacity: 0.45; filter: grayscale(1); }
.cls-name { font-size: 1.0625rem; font-weight: 800; letter-spacing: -0.02em; white-space: nowrap; }
.cls--white .cls-name, .cls--light .cls-name { color: #d1d5db; }
.cls--dark .cls-name { color: rgba(255,255,255,0.18); }
</style>
Props
| Prop | Type | Default | Beschrijving |
|---|---|---|---|
logos * | { name: string; src?: string }[] | — | Klantlogo items |
eyebrow | string | — | Eyebrow |
speed | 'slow' | 'normal' | 'fast' | 'normal' | Scrollsnelheid |
bg | 'white' | 'light' | 'dark' | — | Achtergrond variant |
* = verplicht