FormCheckout Forms
Checkout met contact- en factuurgegevens links en een besteloverzicht rechts.
src/components/forms/FormCheckout.astro
---
/**
* FormCheckout — checkout met contact- en factuurgegevens links, besteloverzicht rechts.
*
* Props:
* - headline?: string
* - summaryTitle?: string
* - products?: { name: string; price: string }[]
* - note?: string
* - button?: string
* - action?: string
*/
interface Props {
headline?: string;
summaryTitle?: string;
products?: { name: string; price: string }[];
note?: string;
button?: string;
action?: string;
}
const {
headline = 'Jouw bestelling',
summaryTitle = 'Overzicht',
products = [
{ name: 'SEO Maandpakket, Starter', price: '€ 449 / mnd' },
{ name: 'Advertentiebeheer', price: '€ 299 / mnd' },
],
note = 'Facturering per e-mail. Opzegging maandelijks mogelijk.',
button = 'Bestelling plaatsen',
action = '#',
} = Astro.props;
---
<section class="bl-section fco">
<div class="bl-inner fco__inner">
<div class="fco__left">
<h2 class="fco__headline">{headline}</h2>
<form class="fco__form" action={action} novalidate>
<fieldset class="fco__fieldset">
<legend class="fco__legend">Contactgegevens</legend>
<div class="fco__row">
<div class="fco__field">
<label class="fco__label" for="fco-voornaam">Voornaam</label>
<input class="fco__input" id="fco-voornaam" type="text" placeholder="Emma" required />
</div>
<div class="fco__field">
<label class="fco__label" for="fco-achternaam">Achternaam</label>
<input class="fco__input" id="fco-achternaam" type="text" placeholder="Bakker" required />
</div>
</div>
<div class="fco__field">
<label class="fco__label" for="fco-email">E-mail</label>
<input class="fco__input" id="fco-email" type="email" placeholder="Je e-mailadres" required />
</div>
<div class="fco__field">
<label class="fco__label" for="fco-bedrijf">Bedrijfsnaam</label>
<input class="fco__input" id="fco-bedrijf" type="text" placeholder="Mijn BV" />
</div>
</fieldset>
<fieldset class="fco__fieldset">
<legend class="fco__legend">Factuuradres</legend>
<div class="fco__field">
<label class="fco__label" for="fco-straat">Straat & huisnummer</label>
<input class="fco__input" id="fco-straat" type="text" placeholder="Keizersgracht 123" required />
</div>
<div class="fco__row">
<div class="fco__field">
<label class="fco__label" for="fco-postcode">Postcode</label>
<input class="fco__input" id="fco-postcode" type="text" placeholder="1234 AB" required />
</div>
<div class="fco__field">
<label class="fco__label" for="fco-plaats">Plaats</label>
<input class="fco__input" id="fco-plaats" type="text" placeholder="Amsterdam" required />
</div>
</div>
</fieldset>
<button class="fco__btn" type="submit">{button}</button>
</form>
</div>
<aside class="fco__summary">
<h3 class="fco__summary-title">{summaryTitle}</h3>
<ul class="fco__products">
{products.map((p) => (
<li class="fco__product">
<span class="fco__product-name">{p.name}</span>
<span class="fco__product-price">{p.price}</span>
</li>
))}
</ul>
<div class="fco__divider"></div>
{note && <div class="fco__note">{note}</div>}
</aside>
</div>
</section>
<style>
.fco{background:#fff}
.fco__inner{display:grid;grid-template-columns:1fr;gap:3rem;align-items:start}
.fco__headline{font-size:clamp(1.5rem,3vw,1.75rem);font-weight:800;color:var(--color-primary, #0a0a0a);letter-spacing:-.02em;margin:0 0 1.75rem}
.fco__form{display:flex;flex-direction:column;gap:1.5rem}
.fco__fieldset{border:1.5px solid #ececec;border-radius:10px;padding:1.25rem;display:flex;flex-direction:column;gap:1rem}
.fco__legend{font-size:.8125rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--color-accent, #6366f1);padding:0 .4rem}
.fco__row{display:grid;grid-template-columns:1fr 1fr;gap:1rem}
.fco__field{display:flex;flex-direction:column;gap:.35rem}
.fco__label{font-size:.9375rem;font-weight:600;color:#374151}
.fco__input{padding:.7rem .9rem;border:1.5px solid #d1d5db;border-radius:7px;font-size:1rem;color:var(--color-primary, #0a0a0a);background:#fafafa;outline:none;font-family:inherit;transition:border-color .2s;width:100%;box-sizing:border-box}
.fco__input:focus{border-color:var(--color-accent, #6366f1);background:#fff}
.fco__btn{padding:.9rem 2rem;background:var(--color-accent, #6366f1);color:#fff;border:none;border-radius:8px;font-size:1rem;font-weight:600;cursor:pointer;transition:opacity .2s;width:100%}
.fco__btn:hover{opacity:.88}
.fco__summary{background:#f6f6fb;border-radius:12px;padding:1.5rem;position:sticky;top:2rem}
.fco__summary-title{font-size:1rem;font-weight:700;color:var(--color-primary, #0a0a0a);margin:0 0 1rem}
.fco__products{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:.75rem}
.fco__product{display:flex;justify-content:space-between;gap:.5rem;font-size:1rem;color:#374151}
.fco__product-name{flex:1}
.fco__product-price{font-weight:600;white-space:nowrap}
.fco__divider{height:1px;background:#ddd;margin:1rem 0}
.fco__note{font-size:.875rem;color:#6b7280;line-height:1.5}
@media(min-width:860px){.fco__inner{grid-template-columns:1fr 320px}}
</style>
Props
| Prop | Type | Default | Beschrijving |
|---|---|---|---|
headline | string | 'Jouw bestelling' | Koptekst formulier |
summaryTitle | string | 'Overzicht' | Titel besteloverzicht |
products | { name: string; price: string }[] | - | Producten in het overzicht |
note | string | - | Voettekst onder het overzicht |
button | string | 'Bestelling plaatsen' | Knoptekst |
action | string | '#' | Form action URL |
* = verplicht