src/components/forms/FormChat.astro
---
/**
* FormChat — chat-widget met bot-header, voorbeeldberichten en invoerveld.
*
* Props:
* - botName?: string
* - avatar?: string enkele letter/teken voor de avatar
* - status?: string
* - messages?: string[] openingsberichten van de bot
* - placeholder?: string
* - disclaimer?: string
* - action?: string
*/
interface Props {
botName?: string;
avatar?: string;
status?: string;
messages?: string[];
placeholder?: string;
disclaimer?: string;
action?: string;
}
const {
botName = 'Online Assistent',
avatar = 'A',
status = 'Online',
messages = [
'Hoi! Ik ben de assistent. Hoe kan ik je helpen vandaag?',
'Je kunt me vragen stellen over onze diensten, prijzen, of gewoon even kennismaken.',
],
placeholder = 'Typ je vraag hier...',
disclaimer = 'Dit is een demo-chatformulier. Reacties zijn niet actief.',
action = '#',
} = Astro.props;
---
<section class="bl-section fch">
<div class="bl-inner fch-inner">
<div class="fch-wrap">
<div class="fch-header">
<div class="fch-avatar" aria-hidden="true">{avatar}</div>
<div>
<h3 class="fch-bot-name">{botName}</h3>
<span class="fch-status"><span class="fch-dot" aria-hidden="true"></span>{status}</span>
</div>
</div>
<div class="fch-messages" role="log" aria-label="Chatberichten" aria-live="polite">
{messages.map((m) => (
<div class="fch-msg fch-msg--bot"><div class="fch-bubble">{m}</div></div>
))}
</div>
<form class="fch-form" action={action} aria-label="Stel een vraag">
<div class="fch-input-wrap">
<input class="fch-input" type="text" name="message" placeholder={placeholder} aria-label="Chatbericht" autocomplete="off" />
<button class="fch-send" type="submit" aria-label="Verstuur bericht">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg>
</button>
</div>
{disclaimer && <p class="fch-disclaimer">{disclaimer}</p>}
</form>
</div>
</div>
</section>
<style>
.fch-wrap{max-width:420px;background:#fff;border:1px solid #e5e5e5;border-radius:16px;overflow:hidden;box-shadow:0 8px 40px #0000001a;display:flex;flex-direction:column}
.fch-header{display:flex;align-items:center;gap:.875rem;padding:1rem 1.25rem;background:var(--color-primary, #0a0a0a)}
.fch-avatar{width:40px;height:40px;border-radius:50%;background:var(--color-accent, #6366f1);color:#fff;font-size:1rem;font-weight:800;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.fch-bot-name{font-size:1rem;font-weight:700;color:#fff;margin:0 0 .15rem}
.fch-status{display:flex;align-items:center;gap:.35rem;font-size:.8125rem;color:#cbd5e1}
.fch-dot{width:7px;height:7px;border-radius:50%;background:#22c55e}
.fch-messages{flex:1;padding:1.25rem;display:flex;flex-direction:column;gap:.75rem;min-height:200px;max-height:320px;overflow-y:auto;background:#f9f9f9}
.fch-msg{display:flex}
.fch-msg--user{justify-content:flex-end}
.fch-bubble{max-width:80%;padding:.65rem 1rem;font-size:1rem;line-height:1.5;border-radius:12px}
.fch-msg--bot .fch-bubble{background:#fff;color:#0a0a0a;border:1px solid #ebebeb;border-bottom-left-radius:4px}
.fch-msg--user .fch-bubble{background:var(--color-accent, #6366f1);color:#fff;border-bottom-right-radius:4px}
.fch-form{padding:1rem 1.25rem;background:#fff;border-top:1px solid #ebebeb}
.fch-input-wrap{display:flex;gap:.5rem;align-items:center}
.fch-input{flex:1;padding:.65rem .9rem;border:1.5px solid #d1d5db;border-radius:8px;font-size:1rem;color:var(--color-primary, #0a0a0a);background:#fff;transition:border-color .2s;font-family:inherit}
.fch-input:focus{outline:none;border-color:var(--color-accent, #6366f1);box-shadow:0 0 0 3px #6366f11f}
.fch-send{width:40px;height:40px;border-radius:8px;background:var(--color-accent, #6366f1);color:#fff;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:opacity .2s}
.fch-send:hover{opacity:.88}
.fch-disclaimer{font-size:.8125rem;color:#6b7280;margin:.5rem 0 0;text-align:center}
</style>
Props
| Prop | Type | Default | Beschrijving |
|---|---|---|---|
botName | string | 'Online Assistent' | Naam van de bot |
avatar | string | 'A' | Avatar-initiaal of teken |
status | string | 'Online' | Statuslabel |
messages | string[] | - | Openingsberichten van de bot |
placeholder | string | - | Placeholder invoerveld |
disclaimer | string | - | Disclaimer onder het invoerveld |
action | string | '#' | Form action URL |
* = verplicht