IconPricing icon
Vergelijkend prijsraster met feature-checklijst per tier. Featured tier krijgt accent-rand en badge.
src/components/icon/IconPricing.astro
---
/**
* IconPricing
* Vergelijkend prijsraster met feature-checklijst per tier.
* Featured tier krijgt accent-rand en badge.
*
* Props:
* - headline?: string
* - tiers: {
* name: string;
* price: string;
* period?: string;
* description?: string;
* badge?: string;
* featured?: boolean;
* cta: { label: string; href: string };
* features: { icon?: string; label: string; included: boolean }[];
* }[]
* - accentColor?: string default '#6366f1'
* - theme?: 'light' | 'dark' default 'light'
*/
interface Feature {
icon?: string;
label: string;
included: boolean;
}
interface Tier {
name: string;
price: string;
period?: string;
description?: string;
badge?: string;
featured?: boolean;
cta: { label: string; href: string };
features: Feature[];
}
interface Props {
headline?: string;
tiers: Tier[];
accentColor?: string;
theme?: 'light' | 'dark';
}
const { headline, tiers, accentColor = '#6366f1', theme = 'light' } = Astro.props;
---
<section class:list={['bl-section', 'ipr', `ipr--${theme}`]}>
<div class="bl-inner ipr-inner" style={`--color-accent: ${accentColor}`}>
{headline && <h2 class="ipr__title">{headline}</h2>}
<div class="ipr__tiers">
{tiers.map(tier => (
<div class:list={['ipr__tier', tier.featured && 'ipr__tier--featured']}>
{tier.badge && <span class="ipr__badge">{tier.badge}</span>}
<p class="ipr__name">{tier.name}</p>
<div class="ipr__price-wrap">
<span class="ipr__price">{tier.price}</span>
{tier.period && <span class="ipr__period">{tier.period}</span>}
</div>
{tier.description && <p class="ipr__desc">{tier.description}</p>}
<ul class="ipr__features">
{tier.features.map(f => (
<li class:list={['ipr__feature', !f.included && 'ipr__feature--excluded']}>
{f.icon && <span class="ipr__feat-icon" aria-hidden="true">{f.icon}</span>}
<span class="ipr__feat-label">{f.label}</span>
<span class:list={['ipr__check', f.included ? 'ipr__check--yes' : 'ipr__check--no']} aria-hidden="true">
{f.included ? '✓' : '✕'}
</span>
</li>
))}
</ul>
<a class:list={['ipr__cta', tier.featured && 'ipr__cta--featured']} href={tier.cta.href}>
{tier.cta.label}
</a>
</div>
))}
</div>
</div>
</section>
<style>
.ipr--light { background: var(--color-bg, #fff); }
.ipr--dark { background: #0a0a0a; }
.ipr__title {
font-size: clamp(1.75rem, 3vw, 2.25rem);
font-weight: 700;
color: var(--color-primary, #0a0a0a);
text-align: center;
margin: 0 0 3rem;
}
.ipr--dark .ipr__title { color: #e8e8e8; }
.ipr__tiers {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
align-items: start;
}
.ipr__tier {
position: relative;
padding: 2rem;
border: 1px solid #eee;
border-radius: 14px;
background: #fff;
}
.ipr--dark .ipr__tier { background: #111; border-color: #333; }
.ipr__tier--featured {
border-color: var(--color-accent);
box-shadow: 0 8px 32px color-mix(in srgb, var(--color-accent) 15%, transparent);
}
.ipr__badge {
position: absolute;
top: -.75rem;
left: 50%;
transform: translate(-50%);
background: var(--color-accent);
color: #fff;
font-size: .72rem;
font-weight: 700;
padding: .25rem 1rem;
border-radius: 20px;
white-space: nowrap;
}
.ipr__name {
font-size: .85rem;
font-weight: 700;
letter-spacing: .1em;
text-transform: uppercase;
color: #888;
margin: 0 0 .5rem;
}
.ipr__price-wrap {
display: flex;
align-items: baseline;
gap: .25rem;
margin-bottom: .5rem;
}
.ipr__price {
font-size: 2.25rem;
font-weight: 900;
color: var(--color-primary, #0a0a0a);
line-height: 1;
}
.ipr--dark .ipr__price { color: #e8e8e8; }
.ipr__period { font-size: .9375rem; color: #999; }
.ipr__desc {
font-size: .9rem;
color: #888;
margin: 0 0 1.5rem;
line-height: 1.5;
}
.ipr__features {
list-style: none;
padding: 0;
margin: 0 0 1.75rem;
display: flex;
flex-direction: column;
gap: .6rem;
}
.ipr__feature {
display: flex;
align-items: center;
gap: .5rem;
font-size: .9rem;
color: var(--color-primary, #0a0a0a);
}
.ipr--dark .ipr__feature { color: #e8e8e8; }
.ipr__feature--excluded { opacity: .4; }
.ipr__feat-icon { font-size: 1rem; }
.ipr__feat-label { flex: 1; }
.ipr__check { font-weight: 700; font-size: .9rem; }
.ipr__check--yes { color: #16a34a; }
.ipr__check--no { color: #dc2626; }
.ipr__cta {
display: block;
text-align: center;
padding: .8rem;
background: #f0f0f0;
color: var(--color-primary, #0a0a0a);
text-decoration: none;
border-radius: 8px;
font-weight: 700;
font-size: 1rem;
transition: opacity .2s;
}
.ipr--dark .ipr__cta { background: #222; color: #e8e8e8; }
.ipr__cta--featured { background: var(--color-accent); color: #fff; }
.ipr__cta:hover { opacity: .9; }
</style>
Props
| Prop | Type | Default | Beschrijving |
|---|---|---|---|
headline | string | - | Optionele sectiekop |
tiers * | Tier[] | - | Prijs-tiers (name, price, period, description, badge, featured, cta, features) |
accentColor | string | '#6366f1' | Kleur voor featured-tier en badges |
theme | 'light' | 'dark' | 'light' | Achtergrondmodus |
* = verplicht