diff --git a/.changeset/dirty-panthers-build.md b/.changeset/dirty-panthers-build.md
new file mode 100644
index 0000000000..4cdea45623
--- /dev/null
+++ b/.changeset/dirty-panthers-build.md
@@ -0,0 +1,13 @@
+---
+'@clerk/chrome-extension': minor
+'@clerk/localizations': minor
+'@clerk/clerk-js': minor
+'@clerk/nextjs': minor
+'@clerk/clerk-react': minor
+'@clerk/types': minor
+---
+
+Introduce the new brand new component
+
+- Lists all the memberships, invitations or suggestions an active user may have
+- Powered by our `useOrganizationList` react hook
diff --git a/packages/chrome-extension/src/__snapshots__/exports.test.ts.snap b/packages/chrome-extension/src/__snapshots__/exports.test.ts.snap
index 8f82a739b7..448480e58f 100644
--- a/packages/chrome-extension/src/__snapshots__/exports.test.ts.snap
+++ b/packages/chrome-extension/src/__snapshots__/exports.test.ts.snap
@@ -9,6 +9,7 @@ exports[`public exports should not include a breaking change 1`] = `
"CreateOrganization",
"MagicLinkErrorCode",
"MultisessionAppSupport",
+ "OrganizationList",
"OrganizationProfile",
"OrganizationSwitcher",
"RedirectToCreateOrganization",
diff --git a/packages/clerk-js/bundlewatch.config.json b/packages/clerk-js/bundlewatch.config.json
index 36d5708d06..4703390f12 100644
--- a/packages/clerk-js/bundlewatch.config.json
+++ b/packages/clerk-js/bundlewatch.config.json
@@ -8,6 +8,7 @@
{ "path": "./dist/impersonationfab*.js", "maxSize": "5KB" },
{ "path": "./dist/organizationprofile*.js", "maxSize": "10KB" },
{ "path": "./dist/organizationswitcher*.js", "maxSize": "5KB" },
+ { "path": "./dist/organizationlist*.js", "maxSize": "5.5KB" },
{ "path": "./dist/signin*.js", "maxSize": "10KB" },
{ "path": "./dist/signup*.js", "maxSize": "10KB" },
{ "path": "./dist/userbutton*.js", "maxSize": "5KB" },
diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts
index b1462c15ad..36a2a5cc3d 100644
--- a/packages/clerk-js/src/core/clerk.ts
+++ b/packages/clerk-js/src/core/clerk.ts
@@ -32,6 +32,7 @@ import type {
InstanceType,
ListenerCallback,
OrganizationInvitationResource,
+ OrganizationListProps,
OrganizationMembershipResource,
OrganizationProfileProps,
OrganizationResource,
@@ -506,6 +507,23 @@ export default class Clerk implements ClerkInterface {
void this.#componentControls?.ensureMounted().then(controls => controls.unmountComponent({ node }));
};
+ public mountOrganizationList = (node: HTMLDivElement, props?: OrganizationListProps) => {
+ this.assertComponentsReady(this.#componentControls);
+ void this.#componentControls?.ensureMounted({ preloadHint: 'OrganizationList' }).then(controls =>
+ controls.mountComponent({
+ name: 'OrganizationList',
+ appearanceKey: 'organizationList',
+ node,
+ props,
+ }),
+ );
+ };
+
+ public unmountOrganizationList = (node: HTMLDivElement): void => {
+ this.assertComponentsReady(this.#componentControls);
+ void this.#componentControls?.ensureMounted().then(controls => controls.unmountComponent({ node }));
+ };
+
public mountUserButton = (node: HTMLDivElement, props?: UserButtonProps) => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls?.ensureMounted({ preloadHint: 'UserButton' }).then(controls =>
diff --git a/packages/clerk-js/src/ui/lazyModules/components.ts b/packages/clerk-js/src/ui/lazyModules/components.ts
index 3f1d60a9ff..f4fe93f9a4 100644
--- a/packages/clerk-js/src/ui/lazyModules/components.ts
+++ b/packages/clerk-js/src/ui/lazyModules/components.ts
@@ -10,6 +10,7 @@ const componentImportPaths = {
import(/* webpackChunkName: "organizationprofile" */ './../components/OrganizationProfile'),
OrganizationSwitcher: () =>
import(/* webpackChunkName: "organizationswitcher" */ './../components/OrganizationSwitcher'),
+ OrganizationList: () => import(/* webpackChunkName: "organizationlist" */ './../components/OrganizationList'),
ImpersonationFab: () => import(/* webpackChunkName: "impersonationfab" */ './../components/ImpersonationFab'),
} as const;
@@ -50,6 +51,10 @@ export const OrganizationSwitcher = lazy(() =>
componentImportPaths.OrganizationSwitcher().then(module => ({ default: module.OrganizationSwitcher })),
);
+export const OrganizationList = lazy(() =>
+ componentImportPaths.OrganizationList().then(module => ({ default: module.OrganizationList })),
+);
+
export const ImpersonationFab = lazy(() =>
componentImportPaths.ImpersonationFab().then(module => ({ default: module.ImpersonationFab })),
);
@@ -64,6 +69,7 @@ export const ClerkComponents = {
UserButton,
UserProfile,
OrganizationSwitcher,
+ OrganizationList,
OrganizationProfile,
CreateOrganization,
SignInModal,
diff --git a/packages/nextjs/src/client-boundary/uiComponents.tsx b/packages/nextjs/src/client-boundary/uiComponents.tsx
index 52b84390d5..ef57bd5d6d 100644
--- a/packages/nextjs/src/client-boundary/uiComponents.tsx
+++ b/packages/nextjs/src/client-boundary/uiComponents.tsx
@@ -15,6 +15,7 @@ export {
SignInButton,
SignUpButton,
SignOutButton,
+ OrganizationList,
} from '@clerk/clerk-react';
export const SignIn = (props: SignInProps) => {
diff --git a/packages/nextjs/src/index.ts b/packages/nextjs/src/index.ts
index 55c663215a..eb4c122a96 100644
--- a/packages/nextjs/src/index.ts
+++ b/packages/nextjs/src/index.ts
@@ -29,6 +29,7 @@ export {
CreateOrganization,
SignInButton,
SignOutButton,
+ OrganizationList,
} from './client-boundary/uiComponents';
/**
diff --git a/packages/react/src/components/index.ts b/packages/react/src/components/index.ts
index 55050610cb..1d00b724a3 100644
--- a/packages/react/src/components/index.ts
+++ b/packages/react/src/components/index.ts
@@ -6,6 +6,7 @@ export {
OrganizationSwitcher,
OrganizationProfile,
CreateOrganization,
+ OrganizationList,
} from './uiComponents';
export {
diff --git a/packages/react/src/components/uiComponents.tsx b/packages/react/src/components/uiComponents.tsx
index f5621dff59..63bd8fe398 100644
--- a/packages/react/src/components/uiComponents.tsx
+++ b/packages/react/src/components/uiComponents.tsx
@@ -1,5 +1,6 @@
import type {
CreateOrganizationProps,
+ OrganizationListProps,
OrganizationProfileProps,
OrganizationSwitcherProps,
SignInProps,
@@ -142,3 +143,14 @@ export const OrganizationSwitcher = withClerk(({ clerk, ...props }: WithClerkPro
/>
);
}, 'OrganizationSwitcher');
+
+export const OrganizationList = withClerk(({ clerk, ...props }: WithClerkProp) => {
+ return (
+
+ );
+}, 'OrganizationList');
diff --git a/packages/react/src/isomorphicClerk.ts b/packages/react/src/isomorphicClerk.ts
index 8927f0d8d6..2a6b3a930d 100644
--- a/packages/react/src/isomorphicClerk.ts
+++ b/packages/react/src/isomorphicClerk.ts
@@ -11,6 +11,7 @@ import type {
HandleMagicLinkVerificationParams,
HandleOAuthCallbackParams,
ListenerCallback,
+ OrganizationListProps,
OrganizationMembershipResource,
OrganizationResource,
RedirectOptions,
@@ -71,6 +72,7 @@ export default class IsomorphicClerk {
private premountOrganizationProfileNodes = new Map();
private premountCreateOrganizationNodes = new Map();
private premountOrganizationSwitcherNodes = new Map();
+ private premountOrganizationListNodes = new Map();
private premountMethodCalls = new Map, MethodCallback>();
private loadedListeners: Array<() => void> = [];
@@ -266,6 +268,10 @@ export default class IsomorphicClerk {
clerkjs.mountUserButton(node, props);
});
+ this.premountOrganizationListNodes.forEach((props: OrganizationListProps, node: HTMLDivElement) => {
+ clerkjs.mountOrganizationList(node, props);
+ });
+
this.#loaded = true;
this.emitLoaded();
return this.clerkjs;
@@ -528,6 +534,22 @@ export default class IsomorphicClerk {
}
};
+ mountOrganizationList = (node: HTMLDivElement, props: OrganizationListProps): void => {
+ if (this.clerkjs && this.#loaded) {
+ this.clerkjs.mountOrganizationList(node, props);
+ } else {
+ this.premountOrganizationListNodes.set(node, props);
+ }
+ };
+
+ unmountOrganizationList = (node: HTMLDivElement): void => {
+ if (this.clerkjs && this.#loaded) {
+ this.clerkjs.unmountOrganizationList(node);
+ } else {
+ this.premountOrganizationListNodes.delete(node);
+ }
+ };
+
mountUserButton = (node: HTMLDivElement, userButtonProps: UserButtonProps): void => {
if (this.clerkjs && this.#loaded) {
this.clerkjs.mountUserButton(node, userButtonProps);
diff --git a/packages/types/src/clerk.ts b/packages/types/src/clerk.ts
index bc334cffd5..90cbf6f837 100644
--- a/packages/types/src/clerk.ts
+++ b/packages/types/src/clerk.ts
@@ -218,14 +218,14 @@ export interface Clerk {
/**
* Mount an organization profile component at the target element.
- * @param targetNode Target to mount the UserProfile component.
+ * @param targetNode Target to mount the OrganizationProfile component.
* @param props Configuration parameters.
*/
mountOrganizationProfile: (targetNode: HTMLDivElement, props?: OrganizationProfileProps) => void;
/**
* Unmount the organization profile component from the target node.
- * @param targetNode Target node to unmount the UserProfile component from.
+ * @param targetNode Target node to unmount the OrganizationProfile component from.
*/
unmountOrganizationProfile: (targetNode: HTMLDivElement) => void;
@@ -244,17 +244,30 @@ export interface Clerk {
/**
* Mount an organization switcher component at the target element.
- * @param targetNode Target to mount the UserProfile component.
+ * @param targetNode Target to mount the OrganizationSwitcher component.
* @param props Configuration parameters.
*/
mountOrganizationSwitcher: (targetNode: HTMLDivElement, props?: OrganizationSwitcherProps) => void;
/**
* Unmount the organization profile component from the target node.*
- * @param targetNode Target node to unmount the UserProfile component from.
+ * @param targetNode Target node to unmount the OrganizationSwitcher component from.
*/
unmountOrganizationSwitcher: (targetNode: HTMLDivElement) => void;
+ /**
+ * Mount an organization list component at the target element.
+ * @param targetNode Target to mount the OrganizationList component.
+ * @param props Configuration parameters.
+ */
+ mountOrganizationList: (targetNode: HTMLDivElement, props?: OrganizationListProps) => void;
+
+ /**
+ * Unmount the organization list component from the target node.*
+ * @param targetNode Target node to unmount the OrganizationList component from.
+ */
+ unmountOrganizationList: (targetNode: HTMLDivElement) => void;
+
/**
* Register a listener that triggers a callback each time important Clerk resources are changed.
* Allows to hook up at different steps in the sign up, sign in processes.