ContactForm
A reusable contact form block with built-in success state, validation support, and i18n capabilities.
Loading...
Basic Usage
import { ContactForm } from "@corew500/ui"
<ContactForm
onFormSubmit={(data) => {
console.log(data)
// { firstName, lastName, email, company, subject, message }
}}
/>With Loading & Success States
const [loading, setLoading] = useState(false)
const [success, setSuccess] = useState(false)
<ContactForm
loading={loading}
success={success}
onFormSubmit={async (data) => {
setLoading(true)
await submitForm(data)
setLoading(false)
setSuccess(true)
}}
successAction={
<Button variant="outline" onClick={() => setSuccess(false)}>
Send another message
</Button>
}
/>Optional Fields
Enable additional fields as needed:
<ContactForm
fields={{
company: true, // Shows company field
subject: true, // Shows subject field
}}
/>Custom Labels (i18n)
Localize all labels and placeholders:
<ContactForm
title="Contactez-nous"
description="Remplissez le formulaire ci-dessous."
submitLabel="Envoyer"
labels={{
firstName: "Prénom",
lastName: "Nom",
email: "Courriel",
company: "Entreprise",
subject: "Sujet",
message: "Message",
}}
placeholders={{
firstName: "Jean",
lastName: "Dupont",
email: "jean@example.com",
company: "Acme Inc.",
subject: "Demande générale",
message: "Votre message...",
}}
/>Validation Errors
Display validation errors for each field:
<ContactForm
errors={{
firstName: "First name is required",
email: "Please enter a valid email address",
message: "Message must be at least 10 characters",
}}
/>Custom Success Content
Customize the success state:
<ContactForm
success={isSuccess}
successTitle="Thank You!"
successDescription="Your message has been received. We'll respond within 24 hours."
successAction={<Button onClick={reset}>Send another</Button>}
/>Props
| Prop | Type | Default | Description |
|---|---|---|---|
| onFormSubmit | (data: ContactFormData) => void | — | Called when the form is submitted with form data |
| loading | enum | false | Whether the form is in a loading state |
| success | enum | false | When true, shows success state instead of form |
| title | string | Send us a message | Custom title for the card header |
| description | string | Fill out the form below and we'll get back to you as soon as possible. | Custom description for the card header |
| successTitle | string | Message Sent! | Title shown in success state |
| successDescription | string | Thank you for reaching out. We'll get back to you shortly. | Description shown in success state |
| successSubDescription | string | — | Secondary description shown in success state |
| successAction | enum | — | Optional action element for success state (e.g., "Send another message" button) |
| submitLabel | string | Send Message | Text for the submit button |
| loadingLabel | string | Sending... | Text shown on submit button while loading |
| fields | { company?: boolean; subject?: boolean; } | {} | Which optional fields to show |
| placeholders | { firstName?: string; lastName?: string; email?: string; company?: string; subject?: string; message?: string; } | {} | Placeholder text for fields |
| labels | { firstName?: string; lastName?: string; email?: string; company?: string; subject?: string; message?: string; } | {} | Field labels (for i18n support) |
| errors | Record<string, string> | {} | Validation error messages keyed by field name |
ContactFormData Type
interface ContactFormData {
firstName: string
lastName: string
email: string
company: string | null
subject: string | null
message: string
}LabelInputContainer Helper
The form also exports a LabelInputContainer component for consistent field layout:
import { LabelInputContainer } from "@corew500/ui"
<LabelInputContainer>
<Label htmlFor="phone">Phone</Label>
<Input id="phone" type="tel" />
</LabelInputContainer>Accessibility
- All inputs have associated labels via
htmlFor/id - Error messages linked via
aria-describedby - Invalid fields marked with
aria-invalid="true" - Submit button disabled during loading
- Success state uses
role="status"for announcements