Components / Blocks
ContactSection
A validated contact form that morphs into a confirmation, support channels, and office cards with local times.
Install
npx shadcn@latest add https://irisui.dev/r/contact-section.jsonimport { ContactSection } from "@/components/iris/blocks/contact-section/contact-section";Preview
ContactSection
A contact page section in three forms: a validated message form that morphs into a confirmation, a list of support channels with a detail pane, or office cards with live local times and open status.
When to use
- A contact or support page where people choose how to reach you.
formto collect a message with a topic;channelsto route people to chat, email, sales or community;officesto show where and when your team is reachable.- Not for a sign up or lead form with many fields: build it from
Inputand friends, or useSignupForm. - Not for in-app help; use a
PopoverorDrawerwith your support widget.
Usage
import { ContactSection } from "@/components/iris/blocks/contact-section/contact-section";
h(ContactSection, {
variant: "form",
title: "Talk to the OpsisID team",
description: "Pricing is by quote. Tell us your purposes, countries and monthly sessions.",
topics: ["Sales", "Support", "Compliance", "Partnerships"],
onSubmit: async ({ name, email, topic, message }) => {
await api.contact({ name, email, topic, message });
},
});
h(ContactSection, {
variant: "offices",
offices: [
{
city: "Athens",
timeZone: "Europe/Athens",
address: ["10 Sample Street, 4th floor", "106 00 Athens, Greece"],
email: "athens@opsisid.example",
hours: [9, 18],
},
],
});
Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant |
"form" | "channels" | "offices" |
"form" |
Which layout to show. |
title / description |
string |
per variant | Heading and supporting text; each variant has its own sample copy for an identity verification team. |
topics |
string[] |
Sales, Support, Compliance, Press | Topic chips in the form. |
onSubmit |
(message: { name, email, topic, message }) => void | Promise<void> |
none | Called with a valid message. Reject to keep the form and show an error; resolve to show the confirmation. |
channels |
ContactChannel[] |
4 sample channels (chat, email, sales, a decision review) | { value, label, meta, icon?, detail: ReactNode }; detail fills the pane when selected. |
channel / defaultChannel / onChannelChange |
string |
first channel | Selected channel (controlled / uncontrolled). |
offices |
ContactOffice[] |
3 sample offices (Athens, Amsterdam, Lisbon) | { city, timeZone (IANA), address: string[], email?, hours?: [open, close] }; hours default to 9 to 18 local time, weekdays. |
className |
string |
none | Extra class on the section. |
Notes
- The message has a 500 character limit with a live counter; name, email and message are validated on submit and focus moves to the first problem.
- Pass your own
channelsfor real use: the defaults are sample copy, and the chat channel's agent shows as an initials avatar. - Office times refresh every 15 seconds, read in 24 hour time, and show Open or Closed from each office's own time zone.
- Topic chips are a radio group and channels a tab list, both with roving focus and arrow keys.
- Reduced motion removes the morph between the form and the confirmation.