Contact Form

Contact section with name, email, a topic select and an auto-growing message textarea with a live character counter, validation that only flags fields after blur, an async submit that shakes on error and morphs the card into a drawn-check thank-you panel, plus a side panel of contact methods.

Preview

Contact Form preview width

Install

Add it with the shadcn CLI, or copy the source manually.

$ bunx --bun shadcn add @karaui/contact-form
@karaui not found? Add it to components.json
{
  "registries": {
    "@karaui": "https://karaui.kamisama-v0.my.id/r/{name}.json"
  }
}

@karaui is in shadcn's public registry directory, so the latest CLI needs no setup. On an older CLI, merge this into the existing file once and every @karaui/… install resolves.

API Reference

defaultValues?
Partial<ContactValues>
—
onSubmit?
((values: ContactValues) => void | Promise<void>)

Called with valid values. Reject with a message to show it and shake the form.

—
validate?
((values: ContactValues) => Partial<Record<keyof ContactValues, string>>)
—
topics?
ContactTopic[]
[ { value: "sales", label: "Sales" }, { value: "support", label: "Support" }, { value: "partnership", label: "Partnership" }, { value: "other", label: "Something else" }, ]
methods?
ContactMethod[]

Side panel rows. Pass `[]` to hide the panel.

[ { id: "email", icon: Mail, label: "Email", value: "hello@example.com", href: "mailto:hello@example.com", }, { id: "chat", icon: MessagesSquare, label: "Live chat", value: "Mon–Fri, 9am–6pm" }, { id: "office", icon: MapPin, label: "Office", value: "100 Example St, Springfield" }, { id: "reply", icon: Clock, label: "Response time", value: "Within one business day" }, ]
maxLength?
number

Character limit for the message (counter shows). Default 500.

500
minLength?
number

Minimum message length. Default 10.

10
title?
ReactNode
Get in touch
description?
ReactNode
Tell us what you need and the right person will reply.
className?
string
—

Keep in mind

Some components on this site are inspired by or recreated from existing work across the web. I'm not here to take credit; just to learn, experiment, and sometimes push things a bit further. If something looks familiar and I forgot to mention you, reach out and I'll fix that right away.

Updated