# ElvixUsername

> Username claim widget with availability check, reserved-word ban, and validation rules baked in. Per-app membership, debounced live check.

<!-- app/account/username-pane.tsx -->
```tsx
"use client";

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

export function UsernamePane() {
  return (
    <ElvixUsername
      onSuccess={(username) => {
        // Saved to the per-app membership. The SDK has already
        // transitioned to its in-frame done pane; the host decides
        // whether to advance onboarding now or wait for dismissal.
        console.log("claimed", username);
      }}
      onFail={(error) => {
        console.warn("username claim failed", error);
      }}
    />
  );
}
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `appId` | `string` | optional | provider `clientId` | App scope. Falls back to the surrounding [`ElvixProvider`](/docs/components/elvix-provider) clientId. |
| `appName` | `string` | optional | provider `appName` | Display name used in copy. Falls back to the provider context. |
| `current` | `string \| null` | optional | membership value | Override the seeded value. Defaults to the username on the current per-app membership. |
| `methodUsername` | `boolean` | optional | `true` | When `false`, the SDK renders a disabled pane explaining the feature is off and points the user at support. |
| `supportUrl` | `string \| null` | optional | provider value | Preferred contact route used by the disabled pane. |
| `supportEmail` | `string \| null` | optional | `null` | Mailto fallback used by the disabled pane when no `supportUrl` is set. |
| `onSuccess` | `(username: string) => void` | optional | (none) | Fires after a successful claim and BEFORE the in-frame done pane. If the callback navigates or unmounts the SDK, the done pane is skipped (host wins). |
| `onFail` | `(error: string) => void` | optional | (none) | Fires alongside the in-frame error pane. Notification-side hook only. |
| `onResult` | `(result: ElvixUsernameResult) => void` | optional | (none) | Terminal callback for every attempt (success and failure). Mirrors the Spine ResponseDto shape. |

> **Note:** Username is per-app, not per-identity. Two apps can have a user with the same username pointing at different humans. Centralised identity fields (name, avatar, region) live on [`ElvixIdentityForm`](/docs/components/elvix-identity-form) and the dedicated per-field components.

> **Warning:** When the host app has username sign-in disabled (`methodUsername=false`), the widget renders a read-only pane and routes the user to `supportUrl` or `supportEmail`. Wire at least one of them on the provider so the disabled state is not a dead end.


## Related

- [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.
- [Avatar](/docs/components/elvix-avatar.md): Centralized avatars, rendered by user id. `ElvixUserAvatar` shows ANY user’s photo from their id alone (no session, no membership) with a custom/OAuth/initials fallback and live cross-app updates. `ElvixAvatar` is the editable wizard that writes the user’s one global photo.
