src/components/cta/CTABanner.astro
---
/**
* CTABanner
* Eenvoudige call-to-action sectie. Groot, direct, converterend.
*
* Props:
* - headline: string
* - sub?: string
* - ctaPrimary: { label: string; href: string }
* - ctaSecondary?: { label: string; href: string }
* - bg?: 'default' | 'dark' | 'accent' | 'gradient'
* - align?: 'center' | 'split' — split = tekst links, CTA rechts
*/
interface Props {
headline: string;
sub?: string;
ctaPrimary: { label: string; href: string };
ctaSecondary?: { label: string; href: string };
bg?: 'default' | 'dark' | 'accent' | 'gradient';
align?: 'center' | 'split';
}
const {
headline,
sub,
ctaPrimary,
ctaSecondary,
bg = 'dark',
align = 'center',
} = Astro.props;
---
<section class={`cta-banner cta-banner--${bg} cta-banner--${align}`}>
<div class="cta-banner__inner">
<div class="cta-banner__text">
<h2 class="cta-banner__headline">{headline}</h2>
{sub && <p class="cta-banner__sub">{sub}</p>}
</div>
<div class="cta-banner__actions">
<a href={ctaPrimary.href} class="cta-banner__btn cta-banner__btn--primary">
{ctaPrimary.label}
</a>
{ctaSecondary && (
<a href={ctaSecondary.href} class="cta-banner__btn cta-banner__btn--ghost">
{ctaSecondary.label}
</a>
)}
</div>
</div>
</section>
<style>
.cta-banner {
padding: 5rem 1.5rem;
background: var(--color-primary);
color: #fff;
}
.cta-banner--default { background: color-mix(in srgb, var(--color-text) 5%, transparent); color: var(--color-text); }
.cta-banner--accent { background: var(--color-accent); }
.cta-banner--gradient {
background: linear-gradient(135deg, var(--color-primary) 0%, color-mix(in srgb, var(--color-accent) 50%, var(--color-primary)) 100%);
}
.cta-banner__inner {
max-width: 1280px;
margin: 0 auto;
}
.cta-banner--center .cta-banner__inner {
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
gap: 2rem;
}
.cta-banner--split .cta-banner__inner {
display: flex;
align-items: center;
justify-content: space-between;
gap: 2rem;
flex-wrap: wrap;
}
.cta-banner__headline {
font-size: clamp(1.75rem, 3.5vw, 2.75rem);
font-weight: 800;
letter-spacing: -0.03em;
margin: 0 0 0.75rem;
}
.cta-banner--center .cta-banner__headline { max-width: 700px; }
.cta-banner__sub {
font-size: 1.0625rem;
opacity: 0.75;
line-height: 1.6;
margin: 0;
max-width: 540px;
}
.cta-banner__actions {
display: flex;
gap: 0.75rem;
flex-wrap: wrap;
flex-shrink: 0;
}
.cta-banner--center .cta-banner__actions { justify-content: center; }
.cta-banner__btn {
display: inline-flex;
align-items: center;
padding: 0.875rem 2rem;
border-radius: var(--radius);
font-weight: 700;
font-size: 1rem;
text-decoration: none;
white-space: nowrap;
transition: opacity 0.2s, transform 0.2s;
}
.cta-banner__btn:hover { opacity: 0.85; transform: translateY(-1px); }
.cta-banner__btn--primary {
background: var(--color-accent);
color: #fff;
}
.cta-banner--accent .cta-banner__btn--primary {
background: #fff;
color: var(--color-accent);
}
.cta-banner__btn--ghost {
background: transparent;
border: 2px solid rgba(255,255,255,0.5);
color: #fff;
}
.cta-banner--default .cta-banner__btn--ghost {
border-color: var(--color-text);
color: var(--color-text);
}
</style>
Props
| Prop | Type | Default | Beschrijving |
|---|---|---|---|
headline * | string | — | Hoofdtekst |
ctaPrimary * | { label: string; href: string } | — | Primaire CTA |
sub | string | — | Ondertekst |
ctaSecondary | { label: string; href: string } | — | Secundaire CTA |
bg | 'default' | 'dark' | 'accent' | 'gradient' | 'dark' | Achtergrondvariant |
align | 'center' | 'split' | 'center' | Center of tekst-links/CTA-rechts |
* = verplicht