Soft card
Contact card with a pill-field form.
Usage
import { ContactSoftCard } from '@/components/blocks/contact-02'
<ContactSoftCard />
// Your own details, an extra phone field and a real submit handler
<ContactSoftCard
title="Talk to our team"
details={[
{ label: 'Email', value: 'team@quillmark.example', href: 'mailto:team@quillmark.example' },
{ label: 'Office', value: '500 Market Street\nSan Diego, CA 92101' },
]}
socials={[{ network: 'x', href: '#' }]}
fields={[
{ name: 'name', label: 'Name', required: true, autoComplete: 'name', width: 'half' },
{ name: 'phone', label: 'Phone', kind: 'tel', autoComplete: 'tel', width: 'half' },
{ name: 'email', label: 'Email', kind: 'email', required: true, autoComplete: 'email' },
{ name: 'message', label: 'Message', kind: 'textarea', required: true, maxLength: 800 },
]}
onSubmit={async (values) => {
const response = await fetch('/api/contact', { method: 'POST', body: JSON.stringify(values) })
if (!response.ok) throw new Error('Failed to send')
}}
/>
Install
pnpm dlx shadcn@latest add @pastaui-pro/contact-02npx shadcn@latest add @pastaui-pro/contact-02yarn dlx shadcn@latest add @pastaui-pro/contact-02bunx --bun shadcn@latest add @pastaui-pro/contact-02Source
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| title | string | = 'We’d love to hear from you' | Card heading. |
| description | ReactNode | = A short reply-time note | Supporting text under the heading. Pass an empty string to hide it. |
| details | ContactCardDetail[] | = Email, phone and office address | Stacked label and value pairs. Add an href to link a value, and use \n to break it onto several lines. |
| socialsLabel | string | = 'Find us elsewhere' | Small label above the social icons. |
| socials | ContactCardSocial[] | = Instagram, X, Facebook and YouTube | Social icon links. network is one of 'instagram', 'x', 'facebook', 'youtube', 'linkedin' or 'tiktok'. Pass an empty array to hide the row. |
| fields | ContactCardField[] | = Name, email, topic and message | Form fields in order. kind is 'text', 'email', 'tel', 'textarea' or 'choice' (a row of pills from options). Set required, autoComplete, minLength, maxLength (shows a counter) and width 'half' to pair two fields. |
| submitLabel | string | = 'Send to the team' | Submit button label. |
| note | string | = 'Answers go out Monday to Friday, 9am to 6pm ET.' | Small line under the button. Pass an empty string to hide it. |
| successTitle | string | = 'Message received' | Heading of the success panel, which receives focus after sending. |
| successMessage | string | = 'It is in our queue now. Expect a reply…' | Text in the success panel. |
| errorMessage | string | = 'Something went wrong and your message was not sent. Please try again.' | Shown under the button when onSubmit throws or rejects. |
| onSubmit | (values: Record<string, string>) => void | Promise<void> | = Simulated success after 1.2s | Called with trimmed values once every field is valid. Throw or reject to show the error state. |
| className | string | = — | Additional classes for the section. |
| style | CSSProperties | = — | Inline styles, handy for overriding the --pp-* theme variables. |