# ElvixRegion

> Single-frame wizard for the user's regional preferences singleton: country cascade plus tap-to-edit on every derived field.

<!-- app/account/region/page.tsx -->
```tsx
"use client";

import { ElvixRegion } from "@elvix.is/sdk/react";

export default function RegionPane() {
  return (
    <ElvixRegion
      onChange={(region) => {
        // Fires on every refresh and after every successful PATCH.
        // `region` is null until the user picks a country.
        console.log("region now", region?.country, region?.locale);
      }}
      onResult={(r) => {
        if (!r.ok) return console.warn(r.error, r.message);
        // Safe to read: country + locale only. Other derived fields
        // (timezone, currency, formats) flow through onChange.
        console.log("saved", r.country, r.locale);
      }}
    />
  );
}
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `height` | `number` | optional | `min(540px, 66dvh)` | Fixed pixel height for the in-frame card. Omit to inherit the responsive default. |
| `minHeight` | `number` | optional | — | Minimum pixel height when `height` is not set. |
| `maxHeight` | `number` | optional | — | Maximum pixel height when `height` is not set. |
| `width` | `number \| string` | optional | `"100%"` | Card width. Numbers are treated as pixels, strings pass through. |
| `onChange` | `(region: RegionRecord \| null) => void` | optional | — | Mirrors the full `RegionRecord` on every refresh and after every successful PATCH. Null until the user picks a country. |
| `onResult` | `(r: ElvixRegionResult) => void` | optional | — | Terminal save callback. Discriminated union: narrow on `r.ok` before reading `r.country` and `r.locale`. Safe metadata only. |

> **Note:** Country edit is the only field that triggers a confirm pane, because it cascades into every derived field (UI locale, time zone, currency, time and date format, number format, measurement, first day of the week). The other field edits PATCH in place without confirmation.

> **Note:** Use `onResult` for toast or analytics (terminal save only). Use `onChange` for live mirroring into local state, since it keeps firing on every refresh including initial load.


## Related

- [ElvixLanguages](/docs/components/elvix-languages.md): Single-frame wizard for spoken languages and CEFR proficiency, capped at 8 with tap-to-edit and delete-confirm.
- [ElvixIdentityForm](/docs/components/elvix-identity-form.md): Hosted profile editor: name, locale, timezone, pronouns, contact. Plugs straight into the elvix User record. In-frame edit → confirm → done lifecycle.
