PricingCompact Sections
Compacte horizontale pricing tabel — plannen als kolommen, features als rijen, check/cross symbolen.
src/components/sections/PricingCompact.astro
---
/**
* PricingCompact
* Compacte horizontale pricing: plannen naast elkaar in één rij,
* features als checklijst, highlighted plan in het midden.
* Geen toggle — simpel en snel scanbaar.
*/
interface Feature {
label: string;
plans: (boolean | string)[];
}
interface Plan {
name: string;
price: string;
period?: string;
description?: string;
ctaLabel?: string;
ctaHref?: string;
highlighted?: boolean;
badge?: string;
}
interface Props {
preHeadline?: string;
headline: string;
sub?: string;
plans: Plan[];
features?: Feature[];
note?: string;
}
const {
preHeadline,
headline,
sub,
plans = [],
features = [],
note,
} = Astro.props;
---
<section class="pc" data-component="pricing-compact">
<div class="pc__inner">
<div class="pc__header">
{preHeadline && <p class="pc__pre">{preHeadline}</p>}
<h2 class="pc__headline" set:html={headline} />
{sub && <p class="pc__sub">{sub}</p>}
</div>
<div class="pc__table-wrap">
<div class="pc__table" style={`--cols:${plans.length + 1}`}>
<!-- Header row: plan names -->
<div class="pc__row pc__row--header">
<div class="pc__cell pc__cell--label"></div>
{plans.map(plan => (
<div class:list={['pc__cell pc__cell--plan', { 'pc__cell--highlighted': plan.highlighted }]}>
{plan.badge && <span class="pc__badge">{plan.badge}</span>}
<span class="pc__plan-name">{plan.name}</span>
<div class="pc__price-wrap">
<span class="pc__price">{plan.price}</span>
{plan.period && <span class="pc__period">/{plan.period}</span>}
</div>
{plan.description && <p class="pc__plan-desc">{plan.description}</p>}
<a href={plan.ctaHref ?? '#'} class:list={['pc__cta', { 'pc__cta--primary': plan.highlighted }]}>
{plan.ctaLabel ?? 'Kies dit plan'}
</a>
</div>
))}
</div>
<!-- Feature rows -->
{features.map((feature, fi) => (
<div class="pc__row">
<div class="pc__cell pc__cell--label">{feature.label}</div>
{plans.map((_, pi) => (
<div class:list={['pc__cell', { 'pc__cell--highlighted': plans[pi].highlighted }]}>
{feature.plans[pi] === true && (
<svg class="pc__check" width="18" height="18" viewBox="0 0 18 18" fill="none">
<path d="M3.5 9l4 4 7-7" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
)}
{feature.plans[pi] === false && (
<svg class="pc__cross" width="18" height="18" viewBox="0 0 18 18" fill="none">
<path d="M5 5l8 8M13 5l-8 8" stroke="currentColor" stroke-width="1.75" stroke-linecap="round"/>
</svg>
)}
{typeof feature.plans[pi] === 'string' && (
<span class="pc__val">{feature.plans[pi]}</span>
)}
</div>
))}
</div>
))}
</div>
</div>
{note && <p class="pc__note">{note}</p>}
</div>
</section>
<style>
.pc {
padding: 6rem 1.5rem;
background: var(--color-bg, #fff);
}
.pc__inner { max-width: 1100px; margin: 0 auto; }
.pc__header {
text-align: center;
max-width: 600px;
margin: 0 auto 4rem;
}
.pc__pre {
font-size: 0.75rem;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--color-accent, #6366f1);
margin-bottom: 0.875rem;
}
.pc__headline {
font-size: clamp(1.75rem, 3.5vw, 3rem);
font-weight: 800;
letter-spacing: -0.035em;
line-height: 1.1;
color: var(--color-primary, #0a0a0a);
margin-bottom: 0.875rem;
}
.pc__headline :global(em) {
font-style: normal;
color: var(--color-accent, #6366f1);
}
.pc__sub {
font-size: 1rem;
line-height: 1.65;
color: var(--color-muted, #6b7280);
}
/* Table */
.pc__table-wrap {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
border-radius: 1rem;
border: 1px solid rgba(0,0,0,0.07);
}
.pc__table {
min-width: 640px;
display: grid;
grid-template-columns: 1.5fr repeat(calc(var(--cols) - 1), 1fr);
}
.pc__row {
display: contents;
}
.pc__cell {
padding: 1.125rem 1.25rem;
border-bottom: 1px solid rgba(0,0,0,0.05);
display: flex;
align-items: center;
justify-content: center;
font-size: 0.9375rem;
color: var(--color-primary, #0a0a0a);
}
.pc__cell--label {
justify-content: flex-start;
font-size: 0.875rem;
color: var(--color-muted, #6b7280);
}
.pc__cell--highlighted {
background: rgba(99,102,241,0.04);
}
.pc__row--header .pc__cell {
flex-direction: column;
align-items: center;
gap: 0.5rem;
padding: 2rem 1.25rem;
border-bottom: 2px solid rgba(0,0,0,0.07);
}
.pc__row--header .pc__cell--highlighted {
background: rgba(99,102,241,0.06);
border-bottom-color: var(--color-accent, #6366f1);
}
.pc__badge {
font-size: 0.6875rem;
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
background: var(--color-accent, #6366f1);
color: #fff;
padding: 0.1875rem 0.625rem;
border-radius: 999px;
}
.pc__plan-name {
font-size: 0.875rem;
font-weight: 700;
letter-spacing: 0.02em;
color: var(--color-primary, #0a0a0a);
}
.pc__price-wrap {
display: flex;
align-items: baseline;
gap: 0.1875rem;
}
.pc__price {
font-size: 2rem;
font-weight: 900;
letter-spacing: -0.04em;
color: var(--color-primary, #0a0a0a);
line-height: 1;
}
.pc__period {
font-size: 0.8125rem;
color: var(--color-muted, #6b7280);
}
.pc__plan-desc {
font-size: 0.8125rem;
color: var(--color-muted, #6b7280);
text-align: center;
line-height: 1.4;
}
.pc__cta {
display: inline-flex;
align-items: center;
background: rgba(0,0,0,0.06);
color: var(--color-primary, #0a0a0a);
padding: 0.625rem 1.25rem;
border-radius: var(--radius, 0.5rem);
font-size: 0.875rem;
font-weight: 700;
text-decoration: none;
transition: background 0.2s;
margin-top: 0.25rem;
}
.pc__cta:hover { background: rgba(0,0,0,0.1); }
.pc__cta--primary {
background: var(--color-accent, #6366f1);
color: #fff;
}
.pc__cta--primary:hover {
background: #4f52d4;
}
.pc__check { color: var(--color-accent, #6366f1); }
.pc__cross { color: rgba(0,0,0,0.2); }
.pc__val {
font-size: 0.875rem;
font-weight: 600;
color: var(--color-primary, #0a0a0a);
}
.pc__note {
text-align: center;
font-size: 0.8125rem;
color: var(--color-muted, #6b7280);
margin-top: 1.5rem;
}
</style>
Props
| Prop | Type | Default | Beschrijving |
|---|---|---|---|
plans * | Plan[] | — | Plannen als kolommen |
features | Feature[] | — | Features met per plan: true/false/string |
headline | string | — | Sectie headline |
* = verplicht