Zoeken...  ⌘K GitHub

IconPricing icon

Vergelijkend prijsraster met feature-checklijst per tier. Featured tier krijgt accent-rand en badge.

/icon-pricing
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