# Contact

A correspondence form, contact facts, questions and location imagery.

- Group: Website
- Import: `import { CorrespondenceSection } from '@misoto22/folio/website'`
- Page: https://ui.misoto22.com/components/contact/

## When to reach for it

Provide localized field labels and host-owned submission state to a complete form.

## Best practices

### Do

- Supply localized labels, descriptive links and meaningful image alternatives.

### Don’t

- Do not put service credentials, routing logic or backend models inside presentation components.

## CorrespondenceSection

A correspondence page's primary content and supporting facts.

### Props

- `aside` (required) — `ReactNode`.
- `children` (required) — `ReactNode`.
- `asidePosition` — `'start' | 'end'` default `'start'`. The secondary column can precede or follow the main content.

Also accepts: `HTMLAttributes<HTMLDivElement>`.

## ContactFormView

Controlled contact form. Validation, submission and delivery remain host responsibilities.

### Props

- `labels` (required) — `ContactFormLabels`.
- `values` (required) — `ContactFormValues`.
- `topics` (required) — `{ value: string; label: string }[]`.
- `topic` (required) — `string`.
- `onTopicChange` (required) — `(value: string) => void`.
- `onFieldChange` (required) — `(field: keyof ContactFormValues, value: string) => void`.
- `onSubmit` (required) — `FormEventHandler<HTMLFormElement>`.
- `limits` (required) — `Record<keyof ContactFormValues, number>`.
- `pending` — `boolean` default `false`.
- `error` — `string`.
- `success` — `{ title: string; description: string }`. A server-confirmed success. The host decides when the form can disappear.
- `idPrefix` — `string`. Optional stable prefix for links to a specific form.

## ContactFacts

Contact facts retain their definition-list semantics and optional navigation.

### Props

- `label` (required) — `string`.
- `items` (required) — `DescriptionListItem[]`.
- `links` — `ReactNode`.
- `linksLabel` — `string`.

## QuestionList

Visible questions and answers, useful when the complete answer set is short.

### Props

- `title` (required) — `string`.
- `description` — `string`.
- `items` (required) — `{ id: string; question: string; answer: string }[]`.

Also accepts: `HTMLAttributes<HTMLElement>`.

## LocationFigure

Static map presentation; provider URLs, credentials and theme selection stay in the host.

### Props

- `label` (required) — `string`.
- `coordinates` (required) — `string`.
- `image` — `ReactNode`.
- `credit` — `ReactNode`.

Also accepts: `HTMLAttributes<HTMLElement>`.

## Example — controlled correspondence

```tsx
import { ContactFormView, type ContactFormValues } from '@misoto22/folio/website'

<ContactFormView
  labels={{ heading: 'Start a conversation', topic: 'Topic', name: 'Name', email: 'Email', subject: 'Subject', message: 'Message',
    namePlaceholder: 'Your name', emailPlaceholder: 'you@example.com', subjectPlaceholder: 'A short introduction', messagePlaceholder: 'What would you like to discuss?',
    optional: 'Optional', note: 'This demonstration saves a local draft only.', submit: 'Capture draft', submitting: 'Capturing' }}
  values={values} onFieldChange={(field, value) => setValues((current) => ({ ...current, [field]: value }))}
  topic={topic} onTopicChange={setTopic} topics={[{ value: 'question', label: 'A question' }, { value: 'project', label: 'A project' }]}
  limits={{ name: 100, email: 200, subject: 160, message: 2000 }}
  onSubmit={(event) => { event.preventDefault(); setSaved(true) }}
  success={saved ? { title: 'Draft captured', description: 'The example retained this draft locally. No message was sent.' } : undefined}
/>
```
