FormProfile Forms
Profielbewerker met avatar, persoonlijke en professionele gegevens en opslaan/annuleren.
src/components/forms/FormProfile.astro
---
/**
* FormProfile — profielbewerker: avatar, persoonlijke en professionele gegevens.
* De ingevulde waarden komen uit props (demo-data in mockProps).
*
* Props:
* - heading?: string
* - initials?: string
* - fullName?: string
* - firstName?: string
* - lastName?: string
* - email?: string
* - phone?: string
* - company?: string
* - role?: string
* - bio?: string
* - submitLabel?: string
* - cancelLabel?: string
*/
interface Props {
heading?: string;
initials?: string;
fullName?: string;
firstName?: string;
lastName?: string;
email?: string;
phone?: string;
company?: string;
role?: string;
bio?: string;
submitLabel?: string;
cancelLabel?: string;
}
const {
heading = 'Profiel bewerken',
initials = 'JV',
fullName = 'Jan de Vries',
firstName = 'Jan',
lastName = 'de Vries',
email = 'jan.de.vries [at] voorbeeld.nl',
phone = '06 - 00 00 00 00',
company = 'Voorbeeld BV',
role = 'Marketing Manager',
bio = 'Marketing professional met 10+ jaar ervaring in e-commerce en B2B.',
submitLabel = 'Wijzigingen opslaan',
cancelLabel = 'Annuleren',
} = Astro.props;
---
<section class="bl-section fpr">
<div class="bl-inner bl-inner--narrow fpr-inner">
<h2 class="fpr-heading">{heading}</h2>
<form class="fpr-form" novalidate>
<div class="fpr-avatar-section">
<div class="fpr-avatar" aria-hidden="true">{initials}</div>
<div>
<p class="fpr-avatar-name">{fullName}</p>
<button class="fpr-avatar-btn" type="button">Foto wijzigen</button>
</div>
</div>
<div class="fpr-section">
<h3 class="fpr-section-title">Persoonlijke gegevens</h3>
<div class="fpr-row">
<div class="fpr-field">
<label class="fpr-label" for="fpr-first">Voornaam</label>
<input class="fpr-input" type="text" id="fpr-first" name="first_name" value={firstName} autocomplete="given-name" />
</div>
<div class="fpr-field">
<label class="fpr-label" for="fpr-last">Achternaam</label>
<input class="fpr-input" type="text" id="fpr-last" name="last_name" value={lastName} autocomplete="family-name" />
</div>
</div>
<div class="fpr-row">
<div class="fpr-field">
<label class="fpr-label" for="fpr-email">E-mailadres</label>
<input class="fpr-input" type="email" id="fpr-email" name="email" value={email} autocomplete="email" />
</div>
<div class="fpr-field">
<label class="fpr-label" for="fpr-phone">Telefoonnummer</label>
<input class="fpr-input" type="tel" id="fpr-phone" name="phone" value={phone} autocomplete="tel" />
</div>
</div>
</div>
<div class="fpr-section">
<h3 class="fpr-section-title">Professionele gegevens</h3>
<div class="fpr-row">
<div class="fpr-field">
<label class="fpr-label" for="fpr-company">Bedrijf</label>
<input class="fpr-input" type="text" id="fpr-company" name="company" value={company} autocomplete="organization" />
</div>
<div class="fpr-field">
<label class="fpr-label" for="fpr-role">Functietitel</label>
<input class="fpr-input" type="text" id="fpr-role" name="role" value={role} autocomplete="organization-title" />
</div>
</div>
<div class="fpr-field">
<label class="fpr-label" for="fpr-bio">Biografie</label>
<textarea class="fpr-textarea" id="fpr-bio" name="bio" rows="3">{bio}</textarea>
</div>
</div>
<div class="fpr-actions">
<button class="fpr-cancel" type="button">{cancelLabel}</button>
<button class="fpr-submit" type="submit">{submitLabel}</button>
</div>
</form>
</div>
</section>
<style>
.fpr-heading{font-size:1.75rem;font-weight:800;color:var(--color-primary, #0a0a0a);margin:0 0 2rem}
.fpr-form{display:flex;flex-direction:column;gap:2rem}
.fpr-avatar-section{display:flex;align-items:center;gap:1.25rem}
.fpr-avatar{width:64px;height:64px;border-radius:50%;background:var(--color-accent, #6366f1);color:#fff;font-size:1.25rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0;letter-spacing:.05em}
.fpr-avatar-name{font-size:1rem;font-weight:700;color:var(--color-primary, #0a0a0a);margin:0 0 .35rem}
.fpr-avatar-btn{font-size:.9rem;color:var(--color-accent, #6366f1);background:none;border:none;cursor:pointer;padding:0;font-weight:600}
.fpr-section{display:flex;flex-direction:column;gap:1.1rem}
.fpr-section-title{font-size:.85rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:#555;margin:0;padding-bottom:.75rem;border-bottom:1px solid #e5e5e5}
.fpr-row{display:grid;grid-template-columns:1fr;gap:1.1rem}
.fpr-field{display:flex;flex-direction:column;gap:.35rem}
.fpr-label{font-size:.95rem;font-weight:600;color:var(--color-primary, #0a0a0a)}
.fpr-input,.fpr-textarea{padding:.7rem .9rem;border:1.5px solid #ddd;border-radius:8px;font-size:1rem;color:var(--color-primary, #0a0a0a);background:#fff;transition:border-color .2s;font-family:inherit;box-sizing:border-box;width:100%}
.fpr-input:focus,.fpr-textarea:focus{outline:none;border-color:var(--color-accent, #6366f1);box-shadow:0 0 0 3px #6366f11f}
.fpr-textarea{resize:vertical;min-height:80px}
.fpr-actions{display:flex;gap:.75rem;justify-content:flex-end;padding-top:.5rem;border-top:1px solid #e5e5e5}
.fpr-cancel{padding:.8rem 1.5rem;background:#f5f5f5;color:#374151;border:none;border-radius:8px;font-size:1rem;font-weight:600;cursor:pointer}
.fpr-submit{padding:.8rem 1.75rem;background:var(--color-accent, #6366f1);color:#fff;border:none;border-radius:8px;font-size:1rem;font-weight:600;cursor:pointer;transition:opacity .2s}
.fpr-submit:hover{opacity:.88}
@media(min-width:600px){.fpr-row{grid-template-columns:1fr 1fr}}
</style>
Props
| Prop | Type | Default | Beschrijving |
|---|---|---|---|
heading | string | 'Profiel bewerken' | Kop boven het formulier |
initials | string | - | Initialen in de avatar |
fullName | string | - | Naam naast de avatar |
firstName | string | - | Waarde voornaam-veld |
lastName | string | - | Waarde achternaam-veld |
email | string | - | Waarde e-mailveld |
phone | string | - | Waarde telefoonveld |
company | string | - | Waarde bedrijfsveld |
role | string | - | Waarde functietitel-veld |
bio | string | - | Waarde biografie-veld |
submitLabel | string | 'Wijzigingen opslaan' | Tekst op de opslaan-knop |
cancelLabel | string | 'Annuleren' | Tekst op de annuleer-knop |
* = verplicht