Zoeken...  ⌘K GitHub

FormChat Forms

Chat-stijl contactformulier.

/form-chat
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