# ElvixIdentityForm

> Hosted profile editor: name, locale, timezone, pronouns, contact. Plugs straight into the elvix User record. In-frame edit → confirm → done lifecycle.

<!-- components/profile-pane.tsx -->
```tsx
"use client";

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

export function ProfilePane() {
  return (
    <ElvixIdentityForm
      onResult={(r) => {
        if (!r.ok) return console.warn("identity save failed", r.error);
        // Saved. The SDK has already written to elvix and transitioned to
        // its in-frame "done" pane. This is the HOST hook: close a modal,
        // refresh a stale cache, toast.
      }}
    />
  );
}
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `initial` | `Partial<IdentityInput>` | optional | fetched on mount | Pre-loaded identity fields (`givenName`, `familyName`, `birthdate`, `gender`, `pronouns`). Omit it and the SDK GETs `/api/account/profile/identity` itself so you don't thread server state in. |
| `onResult` | `(r: ElvixIdentityFormResult) => void` | optional | none | Terminal callback. `r.ok` discriminates success / failure. No PII is echoed back. Fires before the in-frame done pane, so a host that navigates here wins. |

> **Note:** The form reads current values from elvix on mount via the per-app context (`useElvixAppContext()`). You don't need to pass `initial` props: the provider already has them. Same applies to every identity-surface component: [`ElvixUsername`](/docs/components/elvix-username), [`ElvixAvatar`](/docs/components/elvix-avatar), [`ElvixRegion`](/docs/components/elvix-region).


## Related

- [ElvixUsername](/docs/components/elvix-username.md): Username claim widget with availability check, reserved-word ban, and validation rules baked in. Per-app membership, debounced live check.
- [ElvixRegion](/docs/components/elvix-region.md): Single-frame wizard for the user's regional preferences singleton: country cascade plus tap-to-edit on every derived field.
