# Contact Sections

> Four contact sections — details beside a validated form that morphs into a receipt, a stylised SVG map that pans to each office, an office grid with live local times, and support channel cards with availability dots.

- Collection: Blocks
- Tier: pro
- Docs: https://geturui.com/docs/contact-sections
- Install: `npx shadcn@latest add @geturui-pro/contact-sections`
- Dependencies: motion, lucide-react

## Variants

### Form and details

Contact details beside a form with topic chips, a counted message and consent; it validates inline and morphs into a sent receipt with a reference.

Install: `npx shadcn@latest add @geturui-pro/contact-sections-form-split`

| Prop | Type | Default | Description |
|---|---|---|---|
| eyebrow / title / description | `string` | — | Section heading copy (title renders as h2). |
| details | `{ icon; label; value; href? }[]` | — | Contact methods beside the form. |
| topics | `string[]` | — | Multi-select topic chips. |
| onSubmit | `(values: { name; email; company; topics; message }) => void | Promise<void>` | — | Resolve to show the receipt; throw to show the error. |
| replyTime | `string` | "one business day" | Shown on the receipt. |
| className | `string` | — | Classes for the outer element. |

### Map card

A street map drawn in SVG; pins drop in on springs and choosing an office pans the map to it while the glass card crossfades its details.

Install: `npx shadcn@latest add @geturui-pro/contact-sections-map-card`

```tsx
import { ContactMapCard } from "@/components/blocks/contact-sections/map-card";

<ContactMapCard offices={[{ id: "hq", name: "HQ", address: "1 Main St", hours: "Mon–Fri 9–6", x: 0.4, y: 0.4 }]} />
```

| Prop | Type | Default | Description |
|---|---|---|---|
| eyebrow / title / description | `string` | — | Section heading copy (title renders as h2). |
| offices | `{ id; name; address; hours; phone?; x; y; directionsHref? }[]` | — | x and y place the pin, 0–1 across the map. |
| value / defaultValue | `string` | — | Active office id (controlled / uncontrolled). |
| onValueChange | `(id: string) => void` | — | Called when a office is chosen. |
| className | `string` | — | Classes for the outer element. |

### Office locations

Office cards with live local time and open or closed status, copyable addresses, a hover lift and a closing card for remote teams.

Install: `npx shadcn@latest add @geturui-pro/contact-sections-offices-grid`

```tsx
import { ContactOfficesGrid } from "@/components/blocks/contact-sections/offices-grid";

<ContactOfficesGrid offices={[{ id: "ber", city: "Berlin", country: "Germany", address: "Torstraße 1", email: "berlin@acme.com", timeZone: "Europe/Berlin" }]} />
```

| Prop | Type | Default | Description |
|---|---|---|---|
| eyebrow / title / description | `string` | — | Section heading copy (title renders as h2). |
| offices | `{ id; city; country; address; email; timeZone; hours?: [number, number]; caption?; hq? }[]` | — | Offices. timeZone is an IANA zone; hours are local 24h. |
| remote | `{ title; body; linkLabel; href } | null` | — | Closing card; null hides it. |
| className | `string` | — | Classes for the outer element. |

### Support channels

Channel cards with live availability dots, a featured chat card and whole-card hit areas, plus a row of plain help links.

Install: `npx shadcn@latest add @geturui-pro/contact-sections-support-channels`

```tsx
import { ContactSupportChannels } from "@/components/blocks/contact-sections/support-channels";

<ContactSupportChannels links={[{ label: "Status", href: "/status" }]} />
```

| Prop | Type | Default | Description |
|---|---|---|---|
| eyebrow / title / description | `string` | — | Section heading copy (title renders as h2). |
| channels | `{ id; icon; title; description; meta?; status?: "online" | "busy" | "offline"; actionLabel; href?; onAction?; featured?; tag? }[]` | — | Support channels. |
| links | `{ label; href }[]` | — | Plain links under the cards. |
| className | `string` | — | Classes for the outer element. |

## Accessibility

- Every field has a visible label; errors are tied with aria-describedby and focus moves to the first invalid field on submit.
- The receipt takes focus and is a status region; copy buttons announce “Address copied”.
- The map is decorative; offices are a tablist with arrow keys and the details are its tabpanel.
- Local times are computed after mount, so server and client markup match.

## Source

Pro item — send `Authorization: Bearer <registry token>` to include the source.
