TeamAlternating Sections
Uitgebreide alternerende team-layout — grote foto + bio, feiten, quote overlay.
src/components/sections/TeamAlternating.astro
---
/**
* TeamAlternating
* Grote alternerende team member layout — foto + uitgebreide bio.
*/
interface TeamMember {
name: string;
role: string;
bio: string;
image: string;
imageAlt?: string;
facts?: { label: string; value: string; }[];
linkedin?: string;
quote?: string;
}
interface Props {
eyebrow?: string;
headline?: string;
members: TeamMember[];
}
const { eyebrow, headline, members = [] } = Astro.props;
---
<section class="ta" data-component="team-alternating">
<div class="ta__inner">
{(eyebrow || headline) && (
<div class="ta__header">
{eyebrow && <p class="ta__eyebrow">{eyebrow}</p>}
{headline && <h2 class="ta__title" set:html={headline} />}
</div>
)}
{members.map((m, i) => (
<div class:list={['ta__row', { 'ta__row--reversed': i % 2 !== 0 }]}>
<div class="ta__photo">
<img src={m.image} alt={m.imageAlt ?? m.name} loading="lazy" />
{m.quote && (
<div class="ta__quote-card">
<p class="ta__quote-text">"{m.quote}"</p>
</div>
)}
</div>
<div class="ta__content">
<p class="ta__member-role">{m.role}</p>
<h3 class="ta__member-name">{m.name}</h3>
<p class="ta__bio">{m.bio}</p>
{m.facts && m.facts.length > 0 && (
<div class="ta__facts">
{m.facts.map(fact => (
<div class="ta__fact">
<div class="ta__fact-value">{fact.value}</div>
<div class="ta__fact-label">{fact.label}</div>
</div>
))}
</div>
)}
{m.linkedin && (
<a href={m.linkedin} class="ta__linkedin" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
</svg>
Verbinden op LinkedIn
</a>
)}
</div>
</div>
))}
</div>
</section>
<style>
.ta {
background: var(--color-bg, #fff);
padding: 5rem 1.5rem;
}
.ta__inner { max-width: 1100px; margin: 0 auto; }
.ta__header {
text-align: center;
margin-bottom: 4rem;
}
.ta__eyebrow {
font-size: 0.75rem;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--color-accent, #6366f1);
margin-bottom: 0.75rem;
}
.ta__title {
font-size: clamp(1.875rem, 3vw, 2.75rem);
font-weight: 800;
letter-spacing: -0.03em;
color: var(--color-primary, #0a0a0a);
}
.ta__title :global(em) { font-style: normal; color: var(--color-accent, #6366f1); }
.ta__row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4rem;
align-items: center;
padding: 4rem 0;
border-top: 1px solid rgba(0,0,0,0.07);
}
.ta__row--reversed { direction: rtl; }
.ta__row--reversed > * { direction: ltr; }
/* Photo */
.ta__photo {
position: relative;
}
.ta__photo img {
width: 100%;
height: 480px;
object-fit: cover;
object-position: top;
border-radius: calc(var(--radius, 0.5rem) * 2);
display: block;
}
.ta__quote-card {
position: absolute;
bottom: -1.5rem;
right: -1.5rem;
background: #fff;
border: 1px solid rgba(0,0,0,0.07);
border-radius: calc(var(--radius, 0.5rem) * 1.5);
padding: 1.25rem;
max-width: 240px;
box-shadow: 0 12px 32px rgba(0,0,0,0.08);
}
.ta__row--reversed .ta__quote-card {
right: auto;
left: -1.5rem;
}
.ta__quote-text {
font-size: 0.875rem;
line-height: 1.6;
color: var(--color-primary, #0a0a0a);
font-style: italic;
}
/* Content */
.ta__member-role {
font-size: 0.8125rem;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--color-accent, #6366f1);
margin-bottom: 0.5rem;
}
.ta__member-name {
font-size: clamp(1.5rem, 2.5vw, 2.25rem);
font-weight: 800;
letter-spacing: -0.02em;
color: var(--color-primary, #0a0a0a);
margin-bottom: 1rem;
}
.ta__bio {
font-size: 1rem;
line-height: 1.75;
color: var(--color-muted, #6b7280);
margin-bottom: 2rem;
}
.ta__facts {
display: flex;
gap: 2rem;
padding: 1.5rem 0;
border-top: 1px solid rgba(0,0,0,0.07);
border-bottom: 1px solid rgba(0,0,0,0.07);
margin-bottom: 1.5rem;
}
.ta__fact-value {
font-size: 1.75rem;
font-weight: 800;
letter-spacing: -0.03em;
color: var(--color-primary, #0a0a0a);
}
.ta__fact-label {
font-size: 0.8125rem;
color: var(--color-muted, #6b7280);
margin-top: 0.125rem;
}
.ta__linkedin {
display: inline-flex;
align-items: center;
gap: 0.5rem;
color: var(--color-accent, #6366f1);
font-size: 0.9rem;
font-weight: 600;
text-decoration: none;
}
.ta__linkedin:hover { opacity: 0.7; }
@media (max-width: 768px) {
.ta__row { grid-template-columns: 1fr; gap: 2rem; }
.ta__row--reversed { direction: ltr; }
.ta__photo img { height: 300px; }
.ta__quote-card { display: none; }
}
</style>
Props
| Prop | Type | Default | Beschrijving |
|---|---|---|---|
members * | TeamMember[] | — | Team leden met bio, feiten en optionele quote. |
eyebrow | string | — | Label boven sectie |
headline | string | — | Sectie headline |
* = verplicht