src/components/forms/FormChat.astro
---
interface ChatMessage {
role: "bot" | "user";
text: string;
}
interface Props {
heading?: string;
botName?: string;
placeholder?: string;
initialMessages?: ChatMessage[];
}
const {
heading = "Stel een vraag",
botName = "BLURR Assistent",
placeholder = "Typ je vraag hier...",
initialMessages = [
{ role: "bot", text: "Hoi! 👋 Ik ben de BLURR assistent. Hoe kan ik je helpen vandaag?" },
{ role: "bot", text: "Je kunt me vragen stellen over onze diensten, prijzen, of gewoon even kennismaken." },
],
} = Astro.props;
---
<div class="fch-wrap">
<div class="fch-header">
<div class="fch-avatar" aria-hidden="true">B</div>
<div>
<h3 class="fch-bot-name">{botName}</h3>
<span class="fch-status">
<span class="fch-dot" aria-hidden="true"></span>
Online
</span>
</div>
</div>
<div class="fch-messages" role="log" aria-label="Chatberichten" aria-live="polite">
{initialMessages.map(msg => (
<div class={`fch-msg fch-msg--${msg.role}`}>
<div class="fch-bubble">{msg.text}</div>
</div>
))}
</div>
<form class="fch-form" onsubmit="return false;" aria-label={heading}>
<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"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
</button>
</div>
<p class="fch-disclaimer">Dit is een demo-chatformulier. Reacties zijn niet actief.</p>
</form>
</div>
<style>
.fch-wrap {
max-width: 420px;
background: #fff; border: 1px solid #e5e5e5; border-radius: 16px;
overflow: hidden; box-shadow: 0 8px 40px rgba(0,0,0,0.1);
display: flex; flex-direction: column;
}
.fch-header {
display: flex; align-items: center; gap: 0.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: 0.9rem; font-weight: 700; color: #fff; margin: 0 0 0.15rem; }
.fch-status { display: flex; align-items: center; gap: 0.35rem; font-size: 0.75rem; color: rgba(255,255,255,0.6); }
.fch-dot { width: 7px; height: 7px; border-radius: 50%; background: #22c55e; }
.fch-messages {
flex: 1; padding: 1.25rem; display: flex; flex-direction: column; gap: 0.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: 0.65rem 1rem;
font-size: 0.875rem; line-height: 1.5; border-radius: 12px;
}
.fch-msg--bot .fch-bubble { background: #fff; color: #333; 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: 0.5rem; align-items: center; }
.fch-input {
flex: 1; padding: 0.65rem 0.9rem; border: 1.5px solid #ddd; border-radius: 8px;
font-size: 0.9rem; color: var(--color-primary, #0a0a0a); background: #fff;
transition: border-color 0.2s; font-family: inherit;
}
.fch-input:focus { outline: none; border-color: var(--color-accent, #6366f1); box-shadow: 0 0 0 3px rgba(99,102,241,0.12); }
.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 0.2s;
}
.fch-send:hover { opacity: 0.88; }
.fch-disclaimer { font-size: 0.72rem; color: #bbb; margin: 0.5rem 0 0; text-align: center; }
</style>
Props
| Prop | Type | Default | Beschrijving |
|---|---|---|---|
headline | string | — | Formuliertitel |
* = verplicht