> ## Documentation Index
> Fetch the complete documentation index at: https://docs-dev-feat-member-mgmt-docs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage Organization Members on Web

> Learn how to manage Organization members and pending invitations in a tabbed interface with full invitation lifecycle controls.

export const ReleaseStageNotice = ({feature, stage, plans, contact, terms}) => {
  const stageTextMap = {
    "beta": "Beta",
    "ea": "Early Access"
  };
  const stageText = stageTextMap[stage] || "a product release stage";
  const prsLink = "/docs/troubleshoot/product-lifecycle/product-release-stages";
  const linkify = (text, url) => {
    return <a href={url} target="_blank" rel="noreferrer" class="link">{text}</a>;
  };
  const includeDetails = (plans, contact, terms) => {
    const hasDetails = terms || plans || contact;
    if (!hasDetails) return null;
    return <span data-as="p">
            {plans && <>This feature is available for {linkify(`${plans} plans`, "https://auth0.com/pricing")}. </>}
            {contact && "To participate, contact " + contact + ". "}
            {terms && <>By using this feature, you agree to the applicable Free Trial terms in Okta's {linkify("Master Subscription Agreement", "https://www.okta.com/legal")}.</>}
        </span>;
  };
  return <Warning>
            <span data-as="p">
                <strong>The {feature} feature is in {linkify(stageText, prsLink)}.</strong>
            </span>

            {includeDetails(plans, contact, terms)}
        </Warning>;
};

export const ComponentLoader = props => {
  const themePref = window?.localStorage?.getItem?.("isDarkMode");
  const theme = themePref === "dark" || themePref === "light" ? themePref : window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
  const lang = {
    i18n: {
      currentLanguage: props.lang || "en-US"
    }
  };
  return <div style={{
    minHeight: "400px",
    marginTop: "40px",
    background: theme === "light" ? "rgb(var(--gray-950)/.03)" : "rgb(255 255 255/.1)",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    position: "relative",
    backgroundSize: "16px 16px",
    borderRadius: "10px",
    boxShadow: "0 1px 4px 0 rgba(16,30,54,0.04)",
    display: "flex",
    flexDirection: "column"
  }}>
      <div style={{
    minWidth: "320px",
    width: "96.5%",
    maxWidth: "1200px",
    margin: "12px 12px 0",
    background: theme === "light" ? "#ffffff" : "#101011",
    borderRadius: "10px",
    boxShadow: "0 2px 8px 0 rgba(16,30,54,0.04)",
    padding: "24px",
    minHeight: "400px"
  }} data-uc-component={props.componentSelector} data-uc-props={JSON.stringify(lang)}>
        <div aria-label="Loading" role="status" style={{
    position: "absolute",
    top: "50%",
    left: "50%",
    transform: "translate(-50%, -50%)",
    zIndex: 1,
    display: "flex",
    alignItems: "center",
    justifyContent: "center"
  }}>
          <svg width={40} height={40} viewBox="0 0 50 50" style={{
    display: "block"
  }}>
            <circle cx="25" cy="25" r="20" fill="none" stroke="#8A94A6" strokeWidth="5" strokeDasharray="90 150" strokeLinecap="round">
              <animateTransform attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="1s" repeatCount="indefinite" />
            </circle>
          </svg>
        </div>
      </div>
      <div style={{
    width: "100%",
    textAlign: "center",
    color: theme === "light" ? "#6B7280" : "ffffff",
    fontSize: "12px",
    marginTop: "8px",
    marginBottom: "8px",
    letterSpacing: "0.01em",
    fontWeight: 400
  }}>
        {props.componentPreviewText}
      </div>
    </div>;
};

<ReleaseStageNotice feature="Auth0 Universal Components" stage="beta" terms="true" contact="Auth0 Support" />

The `OrganizationMemberManagement` component gives your customers a single tabbed interface for managing who has access to their Auth0 Organization. Organization administrators can review the current member list with assigned roles, invite new members, and manage pending invitations through the full lifecycle—create, view details, copy the invitation URL, revoke, and revoke-and-resend.

With the `OrganizationMemberManagement` component, you do not need to orchestrate navigation, call API endpoints, or manage state. The component loads the current Organization's members and pending invitations from the [My Organization API](/docs/get-started/universal-components/web/components/build-delegated-admin) automatically.

<ComponentLoader componentSelector="organization-member-management" componentPreviewText="Preview of the Organization Member Management component" />

<Tabs>
  <Tab title="React">
    ## Setup requirements

    <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
      **Auth0 Configuration Required**—Ensure your tenant is configured with the
      My Organization API. [View setup guide
      →](/docs/get-started/universal-components/web/components/build-delegated-admin#enable-the-my-organization-api)
    </Callout>

    Removing a member and assigning roles are sensitive mutations that trigger a step-up authentication challenge. Configure your `Auth0Provider` with `interactiveErrorHandler="popup"` so the challenge resolves in a popup without losing page state.

    ## Install the component

    <CodeGroup>
      ```bash pnpm  wrap lines theme={null}
      pnpm add @auth0/universal-components-react
      ```

      ```bash npm wrap lines theme={null}
      npm install @auth0/universal-components-react
      ```
    </CodeGroup>

    <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
      Running either command also installs the @auth0/universal-components-core
      dependency for shared utilities and Auth0 integration.
    </Callout>

    One install covers both React (SPA) and Next.js (RWA). Components are always imported from the root entry `@auth0/universal-components-react`; only `Auth0ComponentProvider` uses a framework-specific subpath—`@auth0/universal-components-react/spa` for React.

    ## Get started

    The component has no required props.

    ```tsx React SPA wrap lines theme={null}
    import { OrganizationMemberManagement } from "@auth0/universal-components-react";

    export function MembersPage() {
      return <OrganizationMemberManagement />;
    }
    ```

    To let administrators drill into a single member, wire `viewMemberDetailsAction` to the route that renders the [`OrganizationMemberDetail`](/docs/get-started/universal-components/web/components/organization-member-detail) component. The action receives `{ userId, tab }`: `userId` flows through to that component's required `userId` prop, and the optional `tab` tells you which tab the administrator asked for.

    ```tsx React SPA wrap lines theme={null}
    import { OrganizationMemberManagement } from "@auth0/universal-components-react";
    import { useNavigate } from "react-router-dom";

    export function MembersPage() {
      const navigate = useNavigate();

      return (
        <OrganizationMemberManagement
          viewMemberDetailsAction={{
            onAfter: ({ userId }) => navigate(`/members/${userId}`),
          }}
        />
      );
    }
    ```

    <Accordion title="Full integration example">
      ```tsx lines theme={null}
      import React from "react";
      import { OrganizationMemberManagement } from "@auth0/universal-components-react";
      import { Auth0Provider } from "@auth0/auth0-react";
      import { Auth0ComponentProvider } from "@auth0/universal-components-react/spa";
      import { useNavigate } from "react-router-dom";
      import { analytics } from "./lib/analytics";
      import { auditLog } from "./lib/audit-log";

      function MembersPage() {
        const navigate = useNavigate();

        return (
          <div className="max-w-6xl mx-auto p-6">
            <OrganizationMemberManagement
              createInvitationAction={{
                onBefore: async (input) => !blocklist.includes(input.invitees[0].email),
                onAfter: (input) => {
                  analytics.track("Invitation Sent", {
                    email: input.invitees[0].email,
                  });
                },
              }}
              revokeInvitationAction={{
                onAfter: () => refetchSeatUsage(),
              }}
              resendInvitationAction={{
                onAfter: (_, newInvitation) => {
                  toast.success(`Invitation resent to ${newInvitation.invitee.email}`);
                },
              }}
              viewMemberDetailsAction={{
                onAfter: ({ userId, tab }) =>
                  navigate(tab ? `/members/${userId}?tab=${tab}` : `/members/${userId}`),
              }}
              removeFromOrganizationAction={{
                onBefore: async (userId) =>
                  confirm(`Remove member ${userId} from the organization?`),
                onAfter: (userId) => {
                  auditLog.record({ action: "member_removed", userId });
                },
              }}
              assignRolesAction={{
                onAfter: ({ userId, roleIds }) => {
                  auditLog.record({ action: "roles_assigned", userId, roleIds });
                },
              }}
              customMessages={{
                header: {
                  title: "Team Members",
                  description: "Manage who has access to your organization",
                },
                tabs: { members: "Members", invitations: "Pending Invites" },
              }}
              styling={{
                variables: {
                  light: { "--color-primary": "#4f46e5" },
                  dark: { "--color-primary": "#818cf8" },
                },
              }}
            />
          </div>
        );
      }

      export default function App() {
        const domain = "YOUR_TENANT.auth0.com";
        const clientId = "YOUR_CLIENT_ID";

        return (
          <Auth0Provider
            domain={domain}
            clientId={clientId}
            authorizationParams={{ redirect_uri: window.location.origin }}
            interactiveErrorHandler="popup"
          >
            <Auth0ComponentProvider domain={domain}>
              <MembersPage />
            </Auth0ComponentProvider>
          </Auth0Provider>
        );
      }
      ```
    </Accordion>

    ## Props

    `OrganizationMemberManagement` has no required props. It loads the current Organization's members and pending invitations from the My Organization API automatically.

    ### Display props

    Display props control how the component renders without affecting its behavior. Use these to hide sections or enable read-only mode.

    | Prop         | Type      | Description                                                             |
    | :----------- | :-------- | :---------------------------------------------------------------------- |
    | `hideHeader` | `boolean` | Hide the component header section. Default: `false`                     |
    | `readOnly`   | `boolean` | Disable all mutation actions (invite, revoke, resend). Default: `false` |

    ***

    ### Action props

    Action props handle user interactions and define what happens when users perform member and invitation operations. Use lifecycle hooks (`onBefore`, `onAfter`) to integrate with your application's routing and analytics.

    | Prop                           | Type                                                       | Description                                                                                                                                                                        |
    | :----------------------------- | :--------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `createInvitationAction`       | `ComponentAction<CreateInvitationInput, MemberInvitation>` | Lifecycle hooks for invitation creation.                                                                                                                                           |
    | `revokeInvitationAction`       | `ComponentAction<MemberInvitation>`                        | Lifecycle hooks for invitation revocation.                                                                                                                                         |
    | `resendInvitationAction`       | `ComponentAction<MemberInvitation, MemberInvitation>`      | Lifecycle hooks for revoke-and-resend.                                                                                                                                             |
    | `viewMemberDetailsAction`      | `ComponentAction<ViewMemberDetailsParams>`                 | Lifecycle hooks for viewing member details. Input is `{ userId, tab }`, where the optional `tab` is `'details'` or `'roles'`. Use `onAfter` to navigate to the member detail page. |
    | `removeFromOrganizationAction` | `ComponentAction<string>`                                  | Lifecycle hooks for member removal. Input is the `userId`.                                                                                                                         |
    | `assignRolesAction`            | `ComponentAction<{ userId: string; roleIds: string[] }>`   | Lifecycle hooks for role assignment to members.                                                                                                                                    |

    **createInvitationAction**

    **Type:** `ComponentAction<CreateInvitationInput, MemberInvitation>`

    Controls the invitation-creation flow. Fires when an administrator submits the "Invite member" modal. Use `onBefore` to validate the invitee list (for example, against a blocklist) and `onAfter` to track analytics or refetch dependent data.

    **Properties:**

    * `disabled`—Hide the "Invite member" button entirely.
    * `onBefore(input)`—Runs before the invitation is sent. Return `false` to cancel. `input.invitees` is the array of invitees being created (one per row in the modal).
    * `onAfter(input, createdInvitation)`—Runs after the invitation is successfully created. Receives both the original input and the created invitation record.

    **Example:**

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      createInvitationAction={{
        onBefore: async (input) => {
          // Validate against a blocklist before sending
          return !blocklist.includes(input.invitees[0].email);
        },
        onAfter: (input) => {
          analytics.track("Invitation Sent", { email: input.invitees[0].email });
        },
      }}
    />
    ```

    ***

    **revokeInvitationAction**

    **Type:** `ComponentAction<MemberInvitation>`

    Controls the invitation-revoke flow. Fires when an administrator revokes a pending invitation from the invitation list. Receives the invitation record being revoked.

    **Properties:**

    * `disabled`—Hide the revoke option in the invitation row menu.
    * `onBefore(invitation)`—Runs before the invitation is revoked. Return `false` to cancel.
    * `onAfter(invitation)`—Runs after the invitation is revoked. Use this to refresh state outside the component.

    **Example:**

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      revokeInvitationAction={{
        onBefore: (invitation) =>
          confirm(`Revoke invitation for ${invitation.invitee.email}?`),
        onAfter: () => refetchSeatUsage(),
      }}
    />
    ```

    ***

    **resendInvitationAction**

    **Type:** `ComponentAction<MemberInvitation, MemberInvitation>`

    Controls the revoke-and-resend flow. The component revokes the original invitation and creates a new one with the same details. `onAfter` receives both the old and the new invitation.

    **Properties:**

    * `disabled`—Hide the resend option in the invitation row menu.
    * `onBefore(invitation)`—Runs before the invitation is resent. Return `false` to cancel.
    * `onAfter(originalInvitation, newInvitation)`—Runs after the new invitation is sent.

    **Example:**

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      resendInvitationAction={{
        onAfter: (original, newInvitation) => {
          toast.success(`Invitation resent to ${newInvitation.invitee.email}`);
          analytics.track("Invitation Resent", { email: original.invitee.email });
        },
      }}
    />
    ```

    ***

    **viewMemberDetailsAction**

    **Type:** `ComponentAction<ViewMemberDetailsParams>`

    Fires when an administrator requests the per-member detail view from the member list. Receives a `ViewMemberDetailsParams` object—the member's `userId`, plus an optional `tab` (`'details'` or `'roles'`) when the request targets a specific tab. The standard wiring is to navigate to the route that renders [`OrganizationMemberDetail`](/docs/get-started/universal-components/web/components/organization-member-detail); `userId` flows through to its required `userId` prop.

    **Properties:**

    * `disabled`—Hide the "View details" entry in the row's actions menu.
    * `onAfter({ userId, tab })`—Runs after the user requests the detail view. Wire this to your router. When `tab` is present, carry it into the destination URL so the detail view opens on the requested tab.

    **Example:**

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      viewMemberDetailsAction={{
        onAfter: ({ userId, tab }) => {
          analytics.track("Member Details Viewed", { userId, tab });
          navigate(tab ? `/members/${userId}?tab=${tab}` : `/members/${userId}`);
        },
      }}
    />
    ```

    ***

    **removeFromOrganizationAction**

    **Type:** `ComponentAction<string>`

    Controls the remove-from-organization flow on a specific member row. Both lifecycle hooks receive the `userId` string directly.

    <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
      This action triggers a step-up authentication challenge. Configure your
      `Auth0Provider` with `interactiveErrorHandler="popup"`.
    </Callout>

    **Properties:**

    * `disabled`—Hide the remove option in the row menu.
    * `onBefore(userId)`—Runs before the member is removed. Return `false` to cancel.
    * `onAfter(userId)`—Runs after the member is removed. Use this to refresh seat usage or write to an audit log.

    **Example:**

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      removeFromOrganizationAction={{
        onBefore: async (userId) =>
          confirm(`Remove member ${userId} from the organization?`),
        onAfter: (userId) => {
          auditLog.record({ action: "member_removed", userId });
          refetchMemberList();
        },
      }}
    />
    ```

    ***

    **assignRolesAction**

    **Type:** `ComponentAction<{ userId: string; roleIds: string[] }>`

    Fires after an administrator assigns one or more roles to a member from the row's role modal. Both lifecycle hooks receive an object with the `userId` and the array of `roleIds` being assigned.

    **Properties:**

    * `disabled`—Hide the assign-roles option.
    * `onBefore({ userId, roleIds })`—Validate the selection. Return `false` to cancel.
    * `onAfter({ userId, roleIds })`—Runs after the roles are assigned. Use this to write to an audit log or refresh role badges.

    **Example:**

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      assignRolesAction={{
        onBefore: ({ roleIds }) => {
          if (roleIds.includes("admin") && roleIds.includes("viewer")) {
            toast.error("Admin and Viewer cannot be assigned together");
            return false;
          }
          return true;
        },
        onAfter: ({ userId, roleIds }) => {
          auditLog.record({ action: "roles_assigned", userId, roleIds });
        },
      }}
    />
    ```

    ***

    ### Customization props

    Customization props let you override default text and apply CSS variables or class names to match your application's design system.

    | Prop             | Type                                            | Description                                                                  |
    | :--------------- | :---------------------------------------------- | :--------------------------------------------------------------------------- |
    | `customMessages` | `Partial<OrganizationMemberManagementMessages>` | Override any default UI text or translations. Default: `{}`                  |
    | `styling`        | `ComponentStyling`                              | CSS variables and class overrides. Default: `{ variables: {}, classes: {} }` |

    **customMessages**

    Customize all text and translations rendered by the component. Every field is optional and falls back to the built-in default. Use this prop to localize the component or to align microcopy with your product voice.

    <Accordion title="Available Messages">
      **header**—Component header

      * `title`, `description`

      **tabs**—Tab labels

      * `members`, `invitations`

      **member.table**—Member table display

      * `columns.name`, `columns.roles`, `columns.last_login`
      * `empty_message`, `search_placeholder`
      * `filter_by_role`, `all_roles`

      **member.actions**—Member row actions

      * `assign_roles`, `remove_from_organization`, `view_details`

      **member.assign\_roles**—Assign roles modal

      * `title`, `description`
      * `roles_label`, `roles_placeholder`
      * `submit_button`, `cancel_button`

      **member.remove\_from\_organization**—Remove member confirmation

      * `title`, `description`
      * `confirm_button`, `cancel_button`

      **invitation.table**—Invitation table display

      * `columns.email`, `columns.status`, `columns.inviter`
      * `columns.created_at`, `columns.expires_at`, `columns.roles`
      * `empty_message`, `search_placeholder`
      * `filter_by_role`, `all_roles`
      * `status_pending`, `status_expired`

      **invitation.create**—Create invitation modal

      * `title`, `description`
      * `email_label`, `email_placeholder`
      * `roles_label`, `provider_label`
      * `submit_button`, `cancel_button`

      **invitation.details**—Invitation details drawer

      * `title`, `email_label`, `status_label`
      * `roles_label`, `provider_label`
      * `copy_url_button`, `revoke_button`, `resend_button`

      **invitation.error / invitation.success**—API responses

      * `error.fetch_failed`, `error.create_failed`, `error.revoke_failed`
      * `success.url_copied`, `success.invitation_resent`
    </Accordion>

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      customMessages={{
        header: {
          title: "Team Members",
          description: "Manage who has access to your organization",
        },
        tabs: { members: "Members", invitations: "Pending Invites" },
        member: {
          table: {
            empty_message: "No members yet.",
            search_placeholder: "Search by name or email...",
          },
          actions: {
            assign_roles: "Assign Roles",
            remove_from_organization: "Remove",
          },
        },
        invitation: {
          table: { empty_message: "No pending invitations." },
          create: { title: "Invite a team member", submit_button: "Send Invite" },
        },
      }}
    />
    ```

    ***

    **styling**

    Customize appearance with CSS variables and class overrides. Variables are theme-aware (separate `light`, `dark`, and `common` scopes); class overrides target named slots inside the component tree so you can attach utility or design-system classes without forking the source.

    <Accordion title="Available Styling Options">
      **Variables**—CSS custom properties

      * `common`—Applied to all themes
      * `light`—Light theme only
      * `dark`—Dark theme only

      **Classes**—Component class overrides

      * `OrganizationMemberManagement-root`
      * `OrganizationMemberManagement-header`
      * `OrganizationMemberManagement-tabs`
      * `OrganizationMemberManagement-tableActions`
      * `OrganizationMemberTab-table`
      * `OrganizationInvitationTab-table`
      * `OrganizationInvitationTab-createModal`
      * `OrganizationInvitationTab-detailsModal`
      * `OrganizationInvitationTab-revokeModal`
      * `OrganizationInvitationTab-revokeResendModal`
    </Accordion>

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      styling={{
        variables: {
          common: { "--font-size-title": "1.5rem" },
          light: { "--color-primary": "#4f46e5" },
          dark: { "--color-primary": "#818cf8" },
        },
        classes: {
          "OrganizationMemberManagement-root": "rounded-xl border shadow-sm",
          "OrganizationMemberManagement-header": "mb-4",
          "OrganizationInvitationTab-table": "mt-4",
        },
      }}
    />
    ```

    ***

    ## Advanced customization

    The `OrganizationMemberManagement` component is composed of smaller subcomponents and hooks. Import them individually to build custom workflows.

    ### Available subcomponents

    | Subcomponent                           | Description                                                                    |
    | :------------------------------------- | :----------------------------------------------------------------------------- |
    | `OrganizationMemberTable`              | Member list with sorting, filtering, role badges, and actions menu             |
    | `OrganizationMemberAssignRolesModal`   | Modal for assigning roles to members                                           |
    | `OrganizationMemberRemoveFromOrgModal` | Confirmation modal for member removal                                          |
    | `OrganizationInvitationTable`          | Invitation list with sorting, filtering, and pagination                        |
    | `OrganizationInvitationCreateModal`    | Modal for sending new invitations                                              |
    | `OrganizationInvitationDetailsModal`   | Drawer showing full invitation details with copy URL, resend, and revoke       |
    | `OrganizationInvitationRevokeModal`    | Confirmation modal for revoke and revoke-and-resend                            |
    | `OrganizationMemberManagementView`     | Stateless view layer—bring your own data via `useOrganizationMemberManagement` |

    ### Available hooks

    These hooks provide the underlying logic without any UI. Use them to build completely custom interfaces while leveraging the Auth0 API integration.

    | Hook                              | Description                                                                                             |
    | :-------------------------------- | :------------------------------------------------------------------------------------------------------ |
    | `useOrganizationMemberManagement` | Data + interaction layer: tab state, member and invitation queries, modal state, and all event handlers |
  </Tab>

  <Tab title="Next.js">
    ## Setup requirements

    <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
      **Auth0 Configuration Required**—Ensure your tenant is configured with the
      My Organization API. [View setup guide
      →](/docs/get-started/universal-components/web/components/build-delegated-admin#configure-auth0-dashboard)
    </Callout>

    Removing a member and assigning roles are sensitive mutations that trigger a step-up authentication challenge. Configure your Auth0 SDK with `interactiveErrorHandler="popup"` so the challenge resolves in a popup without losing page state.

    ## Install component

    <CodeGroup>
      ```bash npm  wrap lines theme={null}
      npm install @auth0/universal-components-react
      ```

      ```bash pnpm wrap lines theme={null}
      pnpm add @auth0/universal-components-react
      ```
    </CodeGroup>

    <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
      Running the pnpm or npm commands installs the @auth0/universal-components-core
      dependency for shared utilities and Auth0 integration.
    </Callout>

    One install covers both React (SPA) and Next.js (RWA). Components are always imported from the root entry `@auth0/universal-components-react`; only `Auth0ComponentProvider` uses a framework-specific subpath—`@auth0/universal-components-react/rwa` for Next.js.

    ## Get started

    The component has no required props.

    ```tsx page.tsx wrap lines theme={null}
    // app/members/page.tsx
    "use client";

    import { OrganizationMemberManagement } from "@auth0/universal-components-react";
    import { useRouter } from "next/navigation";

    export default function MembersPage() {
      const router = useRouter();

      return (
        <OrganizationMemberManagement
          viewMemberDetailsAction={{
            onAfter: ({ userId }) => router.push(`/members/${userId}`),
          }}
        />
      );
    }
    ```

    <Accordion title="Full integration example">
      ```tsx lines theme={null}
      // app/members/page.tsx
      "use client";

      import React from "react";
      import { OrganizationMemberManagement } from "@auth0/universal-components-react";
      import { useRouter } from "next/navigation";
      import { analytics } from "@/lib/analytics";
      import { auditLog } from "@/lib/audit-log";

      export default function MembersPage() {
        const router = useRouter();

        return (
          <div className="max-w-6xl mx-auto p-6">
            <OrganizationMemberManagement
              createInvitationAction={{
                onAfter: (input) => {
                  analytics.track("Invitation Sent", {
                    email: input.invitees[0].email,
                  });
                },
              }}
              revokeInvitationAction={{
                onAfter: () => refetchSeatUsage(),
              }}
              viewMemberDetailsAction={{
                onAfter: ({ userId, tab }) =>
                  router.push(tab ? `/members/${userId}?tab=${tab}` : `/members/${userId}`),
              }}
              removeFromOrganizationAction={{
                onBefore: async (userId) =>
                  confirm(`Remove member ${userId} from the organization?`),
                onAfter: (userId) => {
                  auditLog.record({ action: "member_removed", userId });
                },
              }}
              assignRolesAction={{
                onAfter: ({ userId, roleIds }) => {
                  auditLog.record({ action: "roles_assigned", userId, roleIds });
                },
              }}
              customMessages={{
                header: {
                  title: "Team Members",
                  description: "Manage who has access to your organization",
                },
                tabs: { members: "Members", invitations: "Pending Invites" },
              }}
              styling={{
                variables: {
                  light: { "--color-primary": "#4f46e5" },
                  dark: { "--color-primary": "#818cf8" },
                },
              }}
            />
          </div>
        );
      }
      ```

      Wrap your application with the RWA provider in the root layout:

      ```tsx layout.tsx lines theme={null}
      // app/layout.tsx
      import { Auth0ComponentProvider } from "@auth0/universal-components-react/rwa";

      export default function RootLayout({
        children,
      }: {
        children: React.ReactNode;
      }) {
        return (
          <html lang="en">
            <body>
              <Auth0ComponentProvider domain="YOUR_TENANT.auth0.com">
                {children}
              </Auth0ComponentProvider>
            </body>
          </html>
        );
      }
      ```
    </Accordion>

    ## Props

    `OrganizationMemberManagement` has no required props. It loads the current Organization's members and pending invitations from the My Organization API automatically.

    ### Display props

    Display props control how the component renders without affecting its behavior. Use these to hide sections or enable read-only mode.

    | Prop         | Type      | Description                                                             |
    | :----------- | :-------- | :---------------------------------------------------------------------- |
    | `hideHeader` | `boolean` | Hide the component header section. Default: `false`                     |
    | `readOnly`   | `boolean` | Disable all mutation actions (invite, revoke, resend). Default: `false` |

    ***

    ### Action props

    Action props handle user interactions and define what happens when users perform member and invitation operations. Use lifecycle hooks (`onBefore`, `onAfter`) to integrate with your application's routing and analytics.

    | Prop                           | Type                                                       | Description                                                                                                                                                                        |
    | :----------------------------- | :--------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `createInvitationAction`       | `ComponentAction<CreateInvitationInput, MemberInvitation>` | Lifecycle hooks for invitation creation.                                                                                                                                           |
    | `revokeInvitationAction`       | `ComponentAction<MemberInvitation>`                        | Lifecycle hooks for invitation revocation.                                                                                                                                         |
    | `resendInvitationAction`       | `ComponentAction<MemberInvitation, MemberInvitation>`      | Lifecycle hooks for revoke-and-resend.                                                                                                                                             |
    | `viewMemberDetailsAction`      | `ComponentAction<ViewMemberDetailsParams>`                 | Lifecycle hooks for viewing member details. Input is `{ userId, tab }`, where the optional `tab` is `'details'` or `'roles'`. Use `onAfter` to navigate to the member detail page. |
    | `removeFromOrganizationAction` | `ComponentAction<string>`                                  | Lifecycle hooks for member removal. Input is the `userId`.                                                                                                                         |
    | `assignRolesAction`            | `ComponentAction<{ userId: string; roleIds: string[] }>`   | Lifecycle hooks for role assignment to members.                                                                                                                                    |

    **createInvitationAction**

    **Type:** `ComponentAction<CreateInvitationInput, MemberInvitation>`

    Controls the invitation-creation flow. Fires when an administrator submits the "Invite member" modal. Use `onBefore` to validate the invitee list (for example, against a blocklist) and `onAfter` to track analytics or refetch dependent data.

    **Properties:**

    * `disabled`—Hide the "Invite member" button entirely.
    * `onBefore(input)`—Runs before the invitation is sent. Return `false` to cancel. `input.invitees` is the array of invitees being created (one per row in the modal).
    * `onAfter(input, createdInvitation)`—Runs after the invitation is successfully created. Receives both the original input and the created invitation record.

    **Example:**

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      createInvitationAction={{
        onBefore: async (input) => !blocklist.includes(input.invitees[0].email),
        onAfter: (input) => {
          analytics.track("Invitation Sent", { email: input.invitees[0].email });
        },
      }}
    />
    ```

    ***

    **revokeInvitationAction**

    **Type:** `ComponentAction<MemberInvitation>`

    Controls the invitation-revoke flow. Fires when an administrator revokes a pending invitation from the invitation list. Receives the invitation record being revoked.

    **Properties:**

    * `disabled`—Hide the revoke option in the invitation row menu.
    * `onBefore(invitation)`—Runs before the invitation is revoked. Return `false` to cancel.
    * `onAfter(invitation)`—Runs after the invitation is revoked. Use this to refresh state outside the component.

    **Example:**

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      revokeInvitationAction={{
        onBefore: (invitation) =>
          confirm(`Revoke invitation for ${invitation.invitee.email}?`),
        onAfter: () => refetchSeatUsage(),
      }}
    />
    ```

    ***

    **resendInvitationAction**

    **Type:** `ComponentAction<MemberInvitation, MemberInvitation>`

    Controls the revoke-and-resend flow. The component revokes the original invitation and creates a new one with the same details. `onAfter` receives both the old and the new invitation.

    **Properties:**

    * `disabled`—Hide the resend option in the invitation row menu.
    * `onBefore(invitation)`—Runs before the invitation is resent. Return `false` to cancel.
    * `onAfter(originalInvitation, newInvitation)`—Runs after the new invitation is sent.

    **Example:**

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      resendInvitationAction={{
        onAfter: (original, newInvitation) => {
          toast.success(`Invitation resent to ${newInvitation.invitee.email}`);
          analytics.track("Invitation Resent", { email: original.invitee.email });
        },
      }}
    />
    ```

    ***

    **viewMemberDetailsAction**

    **Type:** `ComponentAction<ViewMemberDetailsParams>`

    Fires when an administrator requests the per-member detail view from the member list. Receives a `ViewMemberDetailsParams` object—the member's `userId`, plus an optional `tab` (`'details'` or `'roles'`) when the request targets a specific tab. The standard wiring is to navigate to the route that renders [`OrganizationMemberDetail`](/docs/get-started/universal-components/web/components/organization-member-detail); `userId` flows through to its required `userId` prop.

    **Properties:**

    * `disabled`—Hide the "View details" entry in the row's actions menu.
    * `onAfter({ userId, tab })`—Runs after the user requests the detail view. Wire this to your router. When `tab` is present, carry it into the destination URL so the detail view opens on the requested tab.

    **Example:**

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      viewMemberDetailsAction={{
        onAfter: ({ userId, tab }) => {
          analytics.track("Member Details Viewed", { userId, tab });
          router.push(tab ? `/members/${userId}?tab=${tab}` : `/members/${userId}`);
        },
      }}
    />
    ```

    ***

    **removeFromOrganizationAction**

    **Type:** `ComponentAction<string>`

    Controls the remove-from-organization flow on a specific member row. Both lifecycle hooks receive the `userId` string directly.

    <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
      This action triggers a step-up authentication challenge. Configure your Auth0
      SDK with `interactiveErrorHandler="popup"`.
    </Callout>

    **Properties:**

    * `disabled`—Hide the remove option in the row menu.
    * `onBefore(userId)`—Runs before the member is removed. Return `false` to cancel.
    * `onAfter(userId)`—Runs after the member is removed. Use this to refresh seat usage or write to an audit log.

    **Example:**

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      removeFromOrganizationAction={{
        onBefore: async (userId) =>
          confirm(`Remove member ${userId} from the organization?`),
        onAfter: (userId) => {
          auditLog.record({ action: "member_removed", userId });
          refetchMemberList();
        },
      }}
    />
    ```

    ***

    **assignRolesAction**

    **Type:** `ComponentAction<{ userId: string; roleIds: string[] }>`

    Fires after an administrator assigns one or more roles to a member from the row's role modal. Both lifecycle hooks receive an object with the `userId` and the array of `roleIds` being assigned.

    **Properties:**

    * `disabled`—Hide the assign-roles option.
    * `onBefore({ userId, roleIds })`—Validate the selection. Return `false` to cancel.
    * `onAfter({ userId, roleIds })`—Runs after the roles are assigned. Use this to write to an audit log or refresh role badges.

    **Example:**

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      assignRolesAction={{
        onBefore: ({ roleIds }) => {
          if (roleIds.includes("admin") && roleIds.includes("viewer")) {
            toast.error("Admin and Viewer cannot be assigned together");
            return false;
          }
          return true;
        },
        onAfter: ({ userId, roleIds }) => {
          auditLog.record({ action: "roles_assigned", userId, roleIds });
        },
      }}
    />
    ```

    ***

    ### Customization props

    Customization props let you override default text and apply CSS variables or class names to match your application's design system.

    | Prop             | Type                                            | Description                                                                  |
    | :--------------- | :---------------------------------------------- | :--------------------------------------------------------------------------- |
    | `customMessages` | `Partial<OrganizationMemberManagementMessages>` | Override any default UI text or translations. Default: `{}`                  |
    | `styling`        | `ComponentStyling`                              | CSS variables and class overrides. Default: `{ variables: {}, classes: {} }` |

    **customMessages**

    Customize all text and translations rendered by the component. Every field is optional and falls back to the built-in default. Use this prop to localize the component or to align microcopy with your product voice.

    <Accordion title="Available Messages">
      **header**—Component header

      * `title`, `description`

      **tabs**—Tab labels

      * `members`, `invitations`

      **member.table**—Member table display

      * `columns.name`, `columns.roles`, `columns.last_login`
      * `empty_message`, `search_placeholder`
      * `filter_by_role`, `all_roles`

      **member.actions**—Member row actions

      * `assign_roles`, `remove_from_organization`, `view_details`

      **member.assign\_roles**—Assign roles modal

      * `title`, `description`
      * `roles_label`, `roles_placeholder`
      * `submit_button`, `cancel_button`

      **member.remove\_from\_organization**—Remove member confirmation

      * `title`, `description`
      * `confirm_button`, `cancel_button`

      **invitation.table**—Invitation table display

      * `columns.email`, `columns.status`, `columns.inviter`
      * `columns.created_at`, `columns.expires_at`, `columns.roles`
      * `empty_message`, `search_placeholder`
      * `filter_by_role`, `all_roles`
      * `status_pending`, `status_expired`

      **invitation.create**—Create invitation modal

      * `title`, `description`
      * `email_label`, `email_placeholder`
      * `roles_label`, `provider_label`
      * `submit_button`, `cancel_button`

      **invitation.details**—Invitation details drawer

      * `title`, `email_label`, `status_label`
      * `roles_label`, `provider_label`
      * `copy_url_button`, `revoke_button`, `resend_button`

      **invitation.error / invitation.success**—API responses

      * `error.fetch_failed`, `error.create_failed`, `error.revoke_failed`
      * `success.url_copied`, `success.invitation_resent`
    </Accordion>

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      customMessages={{
        header: {
          title: "Team Members",
          description: "Manage who has access to your organization",
        },
        tabs: { members: "Members", invitations: "Pending Invites" },
        member: {
          table: {
            empty_message: "No members yet.",
            search_placeholder: "Search by name or email...",
          },
          actions: {
            assign_roles: "Assign Roles",
            remove_from_organization: "Remove",
          },
        },
        invitation: {
          table: { empty_message: "No pending invitations." },
          create: { title: "Invite a team member", submit_button: "Send Invite" },
        },
      }}
    />
    ```

    ***

    **styling**

    Customize appearance with CSS variables and class overrides. Variables are theme-aware (separate `light`, `dark`, and `common` scopes); class overrides target named slots inside the component tree so you can attach utility or design-system classes without forking the source.

    <Accordion title="Available Styling Options">
      **Variables**—CSS custom properties

      * `common`—Applied to all themes
      * `light`—Light theme only
      * `dark`—Dark theme only

      **Classes**—Component class overrides

      * `OrganizationMemberManagement-root`
      * `OrganizationMemberManagement-header`
      * `OrganizationMemberManagement-tabs`
      * `OrganizationMemberManagement-tableActions`
      * `OrganizationMemberTab-table`
      * `OrganizationInvitationTab-table`
      * `OrganizationInvitationTab-createModal`
      * `OrganizationInvitationTab-detailsModal`
      * `OrganizationInvitationTab-revokeModal`
      * `OrganizationInvitationTab-revokeResendModal`
    </Accordion>

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      styling={{
        variables: {
          common: { "--font-size-title": "1.5rem" },
          light: { "--color-primary": "#4f46e5" },
          dark: { "--color-primary": "#818cf8" },
        },
        classes: {
          "OrganizationMemberManagement-root": "rounded-xl border shadow-sm",
          "OrganizationMemberManagement-header": "mb-4",
          "OrganizationInvitationTab-table": "mt-4",
        },
      }}
    />
    ```

    ***

    ## Advanced customization

    The `OrganizationMemberManagement` component is composed of smaller subcomponents and hooks. Import them individually to build custom workflows.

    ### Available subcomponents

    | Subcomponent                           | Description                                                                    |
    | :------------------------------------- | :----------------------------------------------------------------------------- |
    | `OrganizationMemberTable`              | Member list with sorting, filtering, role badges, and actions menu             |
    | `OrganizationMemberAssignRolesModal`   | Modal for assigning roles to members                                           |
    | `OrganizationMemberRemoveFromOrgModal` | Confirmation modal for member removal                                          |
    | `OrganizationInvitationTable`          | Invitation list with sorting, filtering, and pagination                        |
    | `OrganizationInvitationCreateModal`    | Modal for sending new invitations                                              |
    | `OrganizationInvitationDetailsModal`   | Drawer showing full invitation details with copy URL, resend, and revoke       |
    | `OrganizationInvitationRevokeModal`    | Confirmation modal for revoke and revoke-and-resend                            |
    | `OrganizationMemberManagementView`     | Stateless view layer—bring your own data via `useOrganizationMemberManagement` |

    ### Available hooks

    These hooks provide the underlying logic without any UI. Use them to build completely custom interfaces while leveraging the Auth0 API integration.

    | Hook                              | Description                                                                                             |
    | :-------------------------------- | :------------------------------------------------------------------------------------------------------ |
    | `useOrganizationMemberManagement` | Data + interaction layer: tab state, member and invitation queries, modal state, and all event handlers |
  </Tab>

  <Tab title="shadcn">
    ## Setup requirements

    <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
      **Auth0 Configuration Required**—Ensure your tenant is configured with the
      My Organization API. [View setup guide
      →](/docs/get-started/universal-components/web/components/build-delegated-admin#configure-auth0-dashboard)
    </Callout>

    Removing a member and assigning roles are sensitive mutations that trigger a step-up authentication challenge. Configure your `Auth0Provider` with `interactiveErrorHandler="popup"` so the challenge resolves in a popup without losing page state.

    ## Install the component

    Install the component via the shadcn CLI using the GitHub Registry:

    ```bash wrap lines theme={null}
    npx shadcn@latest add auth0/auth0-ui-components/react/my-organization/organization-member-management
    ```

    <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
      The shadcn CLI also installs the `@auth0/universal-components-core`
      dependency for shared utilities and Auth0 integration.
      Requires **shadcn CLI v2.5.0+**.
    </Callout>

    <details>
      <summary>Legacy Vercel registry (deprecated)</summary>

      Existing consumers can continue using the Vercel-hosted path until **September 17, 2026**:

      ```bash wrap lines theme={null}
      npx shadcn@latest add https://auth0-universal-components.vercel.app/r/my-organization/organization-member-management.json
      ```

      New projects should use the GitHub Registry path above.
    </details>

    The CLI installs the React component source code in your `src/components/auth0/` directory along with all UI dependencies and the core package.

    ## Get started

    The component has no required props.

    ```tsx wrap lines theme={null}
    import { OrganizationMemberManagement } from "@/components/auth0/my-organization/organization-member-management";

    export function MembersPage() {
      return <OrganizationMemberManagement />;
    }
    ```

    <Accordion title="Full integration example">
      ```tsx lines theme={null}
      import React from "react";
      import { OrganizationMemberManagement } from "@/components/auth0/my-organization/organization-member-management";
      import { Auth0Provider } from "@auth0/auth0-react";
      import { Auth0ComponentProvider } from "@auth0/universal-components-react/spa";
      import { useNavigate } from "react-router-dom";
      import { analytics } from "./lib/analytics";
      import { auditLog } from "./lib/audit-log";

      function MembersPage() {
        const navigate = useNavigate();

        return (
          <div className="max-w-6xl mx-auto p-6">
            <OrganizationMemberManagement
              createInvitationAction={{
                onAfter: (input) => {
                  analytics.track("Invitation Sent", {
                    email: input.invitees[0].email,
                  });
                },
              }}
              viewMemberDetailsAction={{
                onAfter: ({ userId, tab }) =>
                  navigate(tab ? `/members/${userId}?tab=${tab}` : `/members/${userId}`),
              }}
              removeFromOrganizationAction={{
                onBefore: async (userId) =>
                  confirm(`Remove member ${userId} from the organization?`),
                onAfter: (userId) => {
                  auditLog.record({ action: "member_removed", userId });
                },
              }}
              assignRolesAction={{
                onAfter: ({ userId, roleIds }) => {
                  auditLog.record({ action: "roles_assigned", userId, roleIds });
                },
              }}
              customMessages={{
                header: { title: "Team Members" },
                tabs: { invitations: "Pending Invites" },
              }}
              styling={{
                variables: {
                  light: { "--color-primary": "#4f46e5" },
                  dark: { "--color-primary": "#818cf8" },
                },
              }}
            />
          </div>
        );
      }

      export default function App() {
        const domain = "YOUR_TENANT.auth0.com";
        const clientId = "YOUR_CLIENT_ID";

        return (
          <Auth0Provider
            domain={domain}
            clientId={clientId}
            authorizationParams={{ redirect_uri: window.location.origin }}
            interactiveErrorHandler="popup"
          >
            <Auth0ComponentProvider domain={domain}>
              <MembersPage />
            </Auth0ComponentProvider>
          </Auth0Provider>
        );
      }
      ```
    </Accordion>

    ## Props

    `OrganizationMemberManagement` has no required props. It loads the current Organization's members and pending invitations from the My Organization API automatically.

    ### Display props

    Display props control how the component renders without affecting its behavior. Use these to hide sections or enable read-only mode.

    | Prop         | Type      | Description                                                             |
    | :----------- | :-------- | :---------------------------------------------------------------------- |
    | `hideHeader` | `boolean` | Hide the component header section. Default: `false`                     |
    | `readOnly`   | `boolean` | Disable all mutation actions (invite, revoke, resend). Default: `false` |

    ***

    ### Action props

    Action props handle user interactions and define what happens when users perform member and invitation operations. Use lifecycle hooks (`onBefore`, `onAfter`) to integrate with your application's routing and analytics.

    | Prop                           | Type                                                       | Description                                                                                                                                                                        |
    | :----------------------------- | :--------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `createInvitationAction`       | `ComponentAction<CreateInvitationInput, MemberInvitation>` | Lifecycle hooks for invitation creation.                                                                                                                                           |
    | `revokeInvitationAction`       | `ComponentAction<MemberInvitation>`                        | Lifecycle hooks for invitation revocation.                                                                                                                                         |
    | `resendInvitationAction`       | `ComponentAction<MemberInvitation, MemberInvitation>`      | Lifecycle hooks for revoke-and-resend.                                                                                                                                             |
    | `viewMemberDetailsAction`      | `ComponentAction<ViewMemberDetailsParams>`                 | Lifecycle hooks for viewing member details. Input is `{ userId, tab }`, where the optional `tab` is `'details'` or `'roles'`. Use `onAfter` to navigate to the member detail page. |
    | `removeFromOrganizationAction` | `ComponentAction<string>`                                  | Lifecycle hooks for member removal. Input is the `userId`.                                                                                                                         |
    | `assignRolesAction`            | `ComponentAction<{ userId: string; roleIds: string[] }>`   | Lifecycle hooks for role assignment to members.                                                                                                                                    |

    **createInvitationAction**

    **Type:** `ComponentAction<CreateInvitationInput, MemberInvitation>`

    Controls the invitation-creation flow. Fires when an administrator submits the "Invite member" modal. Use `onBefore` to validate the invitee list (for example, against a blocklist) and `onAfter` to track analytics or refetch dependent data.

    **Properties:**

    * `disabled`—Hide the "Invite member" button entirely.
    * `onBefore(input)`—Runs before the invitation is sent. Return `false` to cancel. `input.invitees` is the array of invitees being created (one per row in the modal).
    * `onAfter(input, createdInvitation)`—Runs after the invitation is successfully created. Receives both the original input and the created invitation record.

    **Example:**

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      createInvitationAction={{
        onBefore: async (input) => !blocklist.includes(input.invitees[0].email),
        onAfter: (input) => {
          analytics.track("Invitation Sent", { email: input.invitees[0].email });
        },
      }}
    />
    ```

    ***

    **revokeInvitationAction**

    **Type:** `ComponentAction<MemberInvitation>`

    Controls the invitation-revoke flow. Fires when an administrator revokes a pending invitation from the invitation list. Receives the invitation record being revoked.

    **Properties:**

    * `disabled`—Hide the revoke option in the invitation row menu.
    * `onBefore(invitation)`—Runs before the invitation is revoked. Return `false` to cancel.
    * `onAfter(invitation)`—Runs after the invitation is revoked. Use this to refresh state outside the component.

    **Example:**

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      revokeInvitationAction={{
        onBefore: (invitation) =>
          confirm(`Revoke invitation for ${invitation.invitee.email}?`),
        onAfter: () => refetchSeatUsage(),
      }}
    />
    ```

    ***

    **resendInvitationAction**

    **Type:** `ComponentAction<MemberInvitation, MemberInvitation>`

    Controls the revoke-and-resend flow. The component revokes the original invitation and creates a new one with the same details. `onAfter` receives both the old and the new invitation.

    **Properties:**

    * `disabled`—Hide the resend option in the invitation row menu.
    * `onBefore(invitation)`—Runs before the invitation is resent. Return `false` to cancel.
    * `onAfter(originalInvitation, newInvitation)`—Runs after the new invitation is sent.

    **Example:**

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      resendInvitationAction={{
        onAfter: (original, newInvitation) => {
          toast.success(`Invitation resent to ${newInvitation.invitee.email}`);
          analytics.track("Invitation Resent", { email: original.invitee.email });
        },
      }}
    />
    ```

    ***

    **viewMemberDetailsAction**

    **Type:** `ComponentAction<ViewMemberDetailsParams>`

    Fires when an administrator requests the per-member detail view from the member list. Receives a `ViewMemberDetailsParams` object—the member's `userId`, plus an optional `tab` (`'details'` or `'roles'`) when the request targets a specific tab. The standard wiring is to navigate to the route that renders [`OrganizationMemberDetail`](/docs/get-started/universal-components/web/components/organization-member-detail); `userId` flows through to its required `userId` prop.

    **Properties:**

    * `disabled`—Hide the "View details" entry in the row's actions menu.
    * `onAfter({ userId, tab })`—Runs after the user requests the detail view. Wire this to your router. When `tab` is present, carry it into the destination URL so the detail view opens on the requested tab.

    **Example:**

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      viewMemberDetailsAction={{
        onAfter: ({ userId, tab }) => {
          analytics.track("Member Details Viewed", { userId, tab });
          navigate(tab ? `/members/${userId}?tab=${tab}` : `/members/${userId}`);
        },
      }}
    />
    ```

    ***

    **removeFromOrganizationAction**

    **Type:** `ComponentAction<string>`

    Controls the remove-from-organization flow on a specific member row. Both lifecycle hooks receive the `userId` string directly.

    <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
      This action triggers a step-up authentication challenge. Configure your
      `Auth0Provider` with `interactiveErrorHandler="popup"`.
    </Callout>

    **Properties:**

    * `disabled`—Hide the remove option in the row menu.
    * `onBefore(userId)`—Runs before the member is removed. Return `false` to cancel.
    * `onAfter(userId)`—Runs after the member is removed. Use this to refresh seat usage or write to an audit log.

    **Example:**

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      removeFromOrganizationAction={{
        onBefore: async (userId) =>
          confirm(`Remove member ${userId} from the organization?`),
        onAfter: (userId) => {
          auditLog.record({ action: "member_removed", userId });
          refetchMemberList();
        },
      }}
    />
    ```

    ***

    **assignRolesAction**

    **Type:** `ComponentAction<{ userId: string; roleIds: string[] }>`

    Fires after an administrator assigns one or more roles to a member from the row's role modal. Both lifecycle hooks receive an object with the `userId` and the array of `roleIds` being assigned.

    **Properties:**

    * `disabled`—Hide the assign-roles option.
    * `onBefore({ userId, roleIds })`—Validate the selection. Return `false` to cancel.
    * `onAfter({ userId, roleIds })`—Runs after the roles are assigned. Use this to write to an audit log or refresh role badges.

    **Example:**

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      assignRolesAction={{
        onBefore: ({ roleIds }) => {
          if (roleIds.includes("admin") && roleIds.includes("viewer")) {
            toast.error("Admin and Viewer cannot be assigned together");
            return false;
          }
          return true;
        },
        onAfter: ({ userId, roleIds }) => {
          auditLog.record({ action: "roles_assigned", userId, roleIds });
        },
      }}
    />
    ```

    ***

    ### Customization props

    Customization props let you override default text and apply CSS variables or class names to match your application's design system.

    | Prop             | Type                                            | Description                                                                  |
    | :--------------- | :---------------------------------------------- | :--------------------------------------------------------------------------- |
    | `customMessages` | `Partial<OrganizationMemberManagementMessages>` | Override any default UI text or translations. Default: `{}`                  |
    | `styling`        | `ComponentStyling`                              | CSS variables and class overrides. Default: `{ variables: {}, classes: {} }` |

    **customMessages**

    Customize all text and translations rendered by the component. Every field is optional and falls back to the built-in default. Use this prop to localize the component or to align microcopy with your product voice.

    <Accordion title="Available Messages">
      **header**—Component header

      * `title`, `description`

      **tabs**—Tab labels

      * `members`, `invitations`

      **member.table**—Member table display

      * `columns.name`, `columns.roles`, `columns.last_login`
      * `empty_message`, `search_placeholder`
      * `filter_by_role`, `all_roles`

      **member.actions**—Member row actions

      * `assign_roles`, `remove_from_organization`, `view_details`

      **member.assign\_roles**—Assign roles modal

      * `title`, `description`
      * `roles_label`, `roles_placeholder`
      * `submit_button`, `cancel_button`

      **member.remove\_from\_organization**—Remove member confirmation

      * `title`, `description`
      * `confirm_button`, `cancel_button`

      **invitation.table**—Invitation table display

      * `columns.email`, `columns.status`, `columns.inviter`
      * `columns.created_at`, `columns.expires_at`, `columns.roles`
      * `empty_message`, `search_placeholder`
      * `filter_by_role`, `all_roles`
      * `status_pending`, `status_expired`

      **invitation.create**—Create invitation modal

      * `title`, `description`
      * `email_label`, `email_placeholder`
      * `roles_label`, `provider_label`
      * `submit_button`, `cancel_button`

      **invitation.details**—Invitation details drawer

      * `title`, `email_label`, `status_label`
      * `roles_label`, `provider_label`
      * `copy_url_button`, `revoke_button`, `resend_button`

      **invitation.error / invitation.success**—API responses

      * `error.fetch_failed`, `error.create_failed`, `error.revoke_failed`
      * `success.url_copied`, `success.invitation_resent`
    </Accordion>

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      customMessages={{
        header: {
          title: "Team Members",
          description: "Manage who has access to your organization",
        },
        tabs: { members: "Members", invitations: "Pending Invites" },
        member: {
          table: {
            empty_message: "No members yet.",
            search_placeholder: "Search by name or email...",
          },
          actions: {
            assign_roles: "Assign Roles",
            remove_from_organization: "Remove",
          },
        },
        invitation: {
          table: { empty_message: "No pending invitations." },
          create: { title: "Invite a team member", submit_button: "Send Invite" },
        },
      }}
    />
    ```

    ***

    **styling**

    Customize appearance with CSS variables and class overrides. Variables are theme-aware (separate `light`, `dark`, and `common` scopes); class overrides target named slots inside the component tree so you can attach utility or design-system classes without forking the source.

    <Accordion title="Available Styling Options">
      **Variables**—CSS custom properties

      * `common`—Applied to all themes
      * `light`—Light theme only
      * `dark`—Dark theme only

      **Classes**—Component class overrides

      * `OrganizationMemberManagement-root`
      * `OrganizationMemberManagement-header`
      * `OrganizationMemberManagement-tabs`
      * `OrganizationMemberManagement-tableActions`
      * `OrganizationMemberTab-table`
      * `OrganizationInvitationTab-table`
      * `OrganizationInvitationTab-createModal`
      * `OrganizationInvitationTab-detailsModal`
      * `OrganizationInvitationTab-revokeModal`
      * `OrganizationInvitationTab-revokeResendModal`
    </Accordion>

    ```tsx wrap lines theme={null}
    <OrganizationMemberManagement
      styling={{
        variables: {
          common: { "--font-size-title": "1.5rem" },
          light: { "--color-primary": "#4f46e5" },
          dark: { "--color-primary": "#818cf8" },
        },
        classes: {
          "OrganizationMemberManagement-root": "rounded-xl border shadow-sm",
          "OrganizationMemberManagement-header": "mb-4",
          "OrganizationInvitationTab-table": "mt-4",
        },
      }}
    />
    ```

    ***

    ## Advanced customization

    The `OrganizationMemberManagement` component is composed of smaller subcomponents and hooks. Because the shadcn CLI installs the source into your project, you can import them individually to build custom workflows.

    ### Available subcomponents

    | Subcomponent                           | Description                                                                    |
    | :------------------------------------- | :----------------------------------------------------------------------------- |
    | `OrganizationMemberTable`              | Member list with sorting, filtering, role badges, and actions menu             |
    | `OrganizationMemberAssignRolesModal`   | Modal for assigning roles to members                                           |
    | `OrganizationMemberRemoveFromOrgModal` | Confirmation modal for member removal                                          |
    | `OrganizationInvitationTable`          | Invitation list with sorting, filtering, and pagination                        |
    | `OrganizationInvitationCreateModal`    | Modal for sending new invitations                                              |
    | `OrganizationInvitationDetailsModal`   | Drawer showing full invitation details with copy URL, resend, and revoke       |
    | `OrganizationInvitationRevokeModal`    | Confirmation modal for revoke and revoke-and-resend                            |
    | `OrganizationMemberManagementView`     | Stateless view layer—bring your own data via `useOrganizationMemberManagement` |

    ### Available hooks

    These hooks provide the underlying logic without any UI. Use them to build completely custom interfaces while leveraging the Auth0 API integration.

    | Hook                              | Description                                                                                             |
    | :-------------------------------- | :------------------------------------------------------------------------------------------------------ |
    | `useOrganizationMemberManagement` | Data + interaction layer: tab state, member and invitation queries, modal state, and all event handlers |
  </Tab>
</Tabs>
