Contact Section React component
A contact section with a heading and your email, phone and address on the left, and a validated message form on the right: topic chips, a loading state driven by your onSubmit promise, inline errors and a thank-you screen.
About the Contact Section component
Contact Section is a complete get-in-touch block. The left side has an eyebrow, a title, a short description and your contact channels (email, phone, office address or live chat), each with an icon and, when you give it an href, a link. The right side is a form card with Name, Email, topic chips and a Message box.
Fields are checked when people leave them or press Send: a missing name, a malformed email and a message shorter than minMessageLength each get an inline error. onSubmit receives { name, email, topic, message }; while its promise runs the button shows a spinner and Sending..., a rejection or a returned string appears as an error above the button, and success fades to a thank-you screen with a Send another message link that clears the form.
When to use it
Use it on a contact page, at the bottom of a landing page, or on an agency or freelancer site where visitors send an enquiry.
Connect onSubmit to your API route, a form service such as Formspree or Resend, or your CRM.
Installation
Add the Contact Section component to your project with the shadcn CLI. It lands in components/contact-section.tsx as plain React + Tailwind CSS source you own and can edit.
npx shadcn@latest add @reactframe/contact-sectionOr copy the source by hand and install its dependencies:
npm install motion clsx tailwind-mergeProps
<ContactSection /> accepts 12 props, all optional.
| Prop | Type | Default |
|---|---|---|
| eyebrow | string | "Contact" |
| title | string | "Let's talk" |
| description | string | "Questions about pricing, a partnership or anything else? Send us a message and we'll get… |
| channels Ways to reach you, listed under the description. Pass [] to hide them. | { kind: "email" | "phone" | "address" | "chat"; label: string; value: string; href?: string }[] | DEFAULT_CHANNELS |
| topics Topic chips above the message. Pass [] to hide them. | string[] | DEFAULT_TOPICS |
| onSubmit Called with the form data. Return a promise: the button shows a spinner while it runs, a rejection (or a resolved string) is shown as an error, and success shows the thank-you screen. | (data: ContactSubmitData) => void | string | Promise<void | string> | — |
| submitLabel | string | "Send message" |
| successTitle | string | "Message sent" |
| successText | string | "Thanks for reaching out. We'll reply to your email within one business day." |
| minMessageLength | number | 10 |
| theme | "dark" | "light" | "dark" |
| className | string | — |
- eyebrowstringDefault: "Contact"
- titlestringDefault: "Let's talk"
- descriptionstringDefault: "Questions about pricing, a partnership or anything else? Send us a message and we'll get…
- channels
Ways to reach you, listed under the description. Pass [] to hide them.
{ kind: "email" | "phone" | "address" | "chat"; label: string; value: string; href?: string }[]Default: DEFAULT_CHANNELS - topics
Topic chips above the message. Pass [] to hide them.
string[]Default: DEFAULT_TOPICS - onSubmit
Called with the form data. Return a promise: the button shows a spinner while it runs, a rejection (or a resolved string) is shown as an error, and success shows the thank-you screen.
(data: ContactSubmitData) => void | string | Promise<void | string> - submitLabelstringDefault: "Send message"
- successTitlestringDefault: "Message sent"
- successTextstringDefault: "Thanks for reaching out. We'll reply to your email within one business day."
- minMessageLengthnumberDefault: 10
- theme"dark" | "light"Default: "dark"
- classNamestring
npm dependencies
Installed for you by the shadcn CLI.
Contact Section FAQ
- How do I send the form to my email?
- Handle onSubmit and post the data to an API route that sends an email (for example with Resend, Postmark or Nodemailer), or to a form service like Formspree. Throw an Error with a message if the request fails and the card shows it.
- Can I change or hide the topics?
- Pass your own list, for example topics={["Sales", "Support"]}, or topics={[]} to hide the chips. The first topic is selected by default and the chosen one is sent as topic.
- Can I hide the email, phone and address list?
- Yes, pass channels={[]}. Each channel takes kind (email, phone, address or chat, which picks the icon), label, value and an optional href.
- Does it work with autofill and screen readers?
- Name and Email use autocomplete name and email. Every field has a label, invalid fields set aria-invalid and point to their error with aria-describedby, the topics are real radio inputs, and the error and success messages are announced.
- How do I change the thank-you message?
- Set successTitle and successText. submitLabel changes the button text.