diff --git a/.changeset/fresh-plums-run.md b/.changeset/fresh-plums-run.md
new file mode 100644
index 00000000000..08cc123c4db
--- /dev/null
+++ b/.changeset/fresh-plums-run.md
@@ -0,0 +1,6 @@
+---
+'@clerk/clerk-js': patch
+'@clerk/types': patch
+---
+
+Hide personal workspace options when organization selection is enforced
diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts
index 58ee4533f35..4960f3f2fc4 100644
--- a/packages/clerk-js/src/core/clerk.ts
+++ b/packages/clerk-js/src/core/clerk.ts
@@ -829,7 +829,12 @@ export class Clerk implements ClerkInterface {
}),
);
- this.telemetry?.record(eventPrebuiltComponentMounted('OrganizationSwitcher', props));
+ this.telemetry?.record(
+ eventPrebuiltComponentMounted('OrganizationSwitcher', {
+ ...props,
+ forceOrganizationSelection: this.environment?.organizationSettings.forceOrganizationSelection,
+ }),
+ );
};
public unmountOrganizationSwitcher = (node: HTMLDivElement): void => {
@@ -863,7 +868,12 @@ export class Clerk implements ClerkInterface {
}),
);
- this.telemetry?.record(eventPrebuiltComponentMounted('OrganizationList', props));
+ this.telemetry?.record(
+ eventPrebuiltComponentMounted('OrganizationList', {
+ ...props,
+ forceOrganizationSelection: this.environment?.organizationSettings.forceOrganizationSelection,
+ }),
+ );
};
public unmountOrganizationList = (node: HTMLDivElement): void => {
diff --git a/packages/clerk-js/src/core/resources/OrganizationSettings.ts b/packages/clerk-js/src/core/resources/OrganizationSettings.ts
index ea49f111865..09edfd6b58b 100644
--- a/packages/clerk-js/src/core/resources/OrganizationSettings.ts
+++ b/packages/clerk-js/src/core/resources/OrganizationSettings.ts
@@ -20,6 +20,7 @@ export class OrganizationSettings extends BaseResource implements OrganizationSe
};
enabled: boolean = false;
maxAllowedMemberships: number = 1;
+ forceOrganizationSelection!: boolean;
public constructor(data: OrganizationSettingsJSON | OrganizationSettingsJSONSnapshot | null = null) {
super();
@@ -43,6 +44,10 @@ export class OrganizationSettings extends BaseResource implements OrganizationSe
this.enabled = this.withDefault(data.enabled, this.enabled);
this.maxAllowedMemberships = this.withDefault(data.max_allowed_memberships, this.maxAllowedMemberships);
+ this.forceOrganizationSelection = this.withDefault(
+ data.force_organization_selection,
+ this.forceOrganizationSelection,
+ );
return this;
}
diff --git a/packages/clerk-js/src/core/resources/__tests__/Environment.test.ts b/packages/clerk-js/src/core/resources/__tests__/Environment.test.ts
index e1f996a7d04..4fcb37f622d 100644
--- a/packages/clerk-js/src/core/resources/__tests__/Environment.test.ts
+++ b/packages/clerk-js/src/core/resources/__tests__/Environment.test.ts
@@ -237,6 +237,7 @@ describe('Environment', () => {
organization_settings: {
enabled: false,
max_allowed_memberships: 5,
+ force_organization_selection: false,
actions: { admin_delete: true },
domains: { enabled: false, enrollment_modes: [], default_role: null },
},
diff --git a/packages/clerk-js/src/core/resources/__tests__/__snapshots__/Environment.test.ts.snap b/packages/clerk-js/src/core/resources/__tests__/__snapshots__/Environment.test.ts.snap
index 1fe9cb48a80..085b8619913 100644
--- a/packages/clerk-js/src/core/resources/__tests__/__snapshots__/Environment.test.ts.snap
+++ b/packages/clerk-js/src/core/resources/__tests__/__snapshots__/Environment.test.ts.snap
@@ -581,6 +581,7 @@ Environment {
"enrollmentModes": [],
},
"enabled": false,
+ "forceOrganizationSelection": false,
"maxAllowedMemberships": 5,
"pathRoot": "",
},
diff --git a/packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx b/packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
index fb58320fce9..f223debb93f 100644
--- a/packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
+++ b/packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx
@@ -185,6 +185,24 @@ describe('OrganizationList', () => {
expect(queryByRole('button', { name: 'Join' })).not.toBeInTheDocument();
});
});
+
+ describe('with force organization selection setting on environment', () => {
+ it('does not show the personal account', async () => {
+ const { wrapper } = await createFixtures(f => {
+ f.withOrganizations();
+ f.withForceOrganizationSelection();
+ f.withUser({
+ email_addresses: ['test@clerk.com'],
+ organization_memberships: [{ name: 'Org1', id: '1', role: 'admin' }],
+ });
+ });
+ const { queryByText } = render(, { wrapper });
+
+ await waitFor(() => {
+ expect(queryByText('Personal account')).not.toBeInTheDocument();
+ });
+ });
+ });
});
describe('CreateOrganization', () => {
diff --git a/packages/clerk-js/src/ui/components/OrganizationSwitcher/__tests__/OrganizationSwitcher.test.tsx b/packages/clerk-js/src/ui/components/OrganizationSwitcher/__tests__/OrganizationSwitcher.test.tsx
index bac49c52af3..8ec33fee42b 100644
--- a/packages/clerk-js/src/ui/components/OrganizationSwitcher/__tests__/OrganizationSwitcher.test.tsx
+++ b/packages/clerk-js/src/ui/components/OrganizationSwitcher/__tests__/OrganizationSwitcher.test.tsx
@@ -45,6 +45,19 @@ describe('OrganizationSwitcher', () => {
expect(queryByText('Personal Workspace')).toBeNull();
expect(getByText('No organization selected')).toBeInTheDocument();
});
+
+ describe('with force organization selection setting on environment', () => {
+ it('does not show the personal workspace', async () => {
+ const { wrapper } = await createFixtures(f => {
+ f.withOrganizations();
+ f.withForceOrganizationSelection();
+ f.withUser({ email_addresses: ['test@clerk.com'] });
+ });
+ const { queryByText, getByRole, userEvent } = render(, { wrapper });
+ await userEvent.click(getByRole('button'));
+ expect(queryByText('Personal Workspace')).toBeNull();
+ });
+ });
});
describe('OrganizationSwitcherTrigger', () => {
diff --git a/packages/clerk-js/src/ui/components/SessionTask/SessionTask.tsx b/packages/clerk-js/src/ui/components/SessionTask/SessionTask.tsx
index b869d62265e..dbfed04a19c 100644
--- a/packages/clerk-js/src/ui/components/SessionTask/SessionTask.tsx
+++ b/packages/clerk-js/src/ui/components/SessionTask/SessionTask.tsx
@@ -7,8 +7,12 @@ import { OrganizationList } from '../OrganizationList';
const ContentRegistry: Record = {
org: () => (
- // TODO - Hide personal workspace within organization list context based on environment
-
+
),
diff --git a/packages/clerk-js/src/ui/contexts/components/OrganizationList.ts b/packages/clerk-js/src/ui/contexts/components/OrganizationList.ts
index ba86a6e1a4f..0c07c4161f4 100644
--- a/packages/clerk-js/src/ui/contexts/components/OrganizationList.ts
+++ b/packages/clerk-js/src/ui/contexts/components/OrganizationList.ts
@@ -11,7 +11,7 @@ export const OrganizationListContext = createContext
export const useOrganizationListContext = () => {
const context = useContext(OrganizationListContext);
const { navigate } = useRouter();
- const { displayConfig } = useEnvironment();
+ const { displayConfig, organizationSettings } = useEnvironment();
if (!context || context.componentName !== 'OrganizationList') {
throw new Error('Clerk: useOrganizationListContext called outside OrganizationList.');
@@ -80,7 +80,7 @@ export const useOrganizationListContext = () => {
afterCreateOrganizationUrl,
skipInvitationScreen: ctx.skipInvitationScreen || false,
hideSlug: ctx.hideSlug || false,
- hidePersonal: ctx.hidePersonal || false,
+ hidePersonal: organizationSettings.forceOrganizationSelection || ctx.hidePersonal || false,
navigateAfterCreateOrganization,
navigateAfterSelectOrganization,
navigateAfterSelectPersonal,
diff --git a/packages/clerk-js/src/ui/contexts/components/OrganizationSwitcher.ts b/packages/clerk-js/src/ui/contexts/components/OrganizationSwitcher.ts
index e4ceffde605..b4afacd7bd5 100644
--- a/packages/clerk-js/src/ui/contexts/components/OrganizationSwitcher.ts
+++ b/packages/clerk-js/src/ui/contexts/components/OrganizationSwitcher.ts
@@ -11,7 +11,7 @@ export const OrganizationSwitcherContext = createContext {
const context = useContext(OrganizationSwitcherContext);
const { navigate } = useRouter();
- const { displayConfig } = useEnvironment();
+ const { displayConfig, organizationSettings } = useEnvironment();
if (!context || context.componentName !== 'OrganizationSwitcher') {
throw new Error('Clerk: useOrganizationSwitcherContext called outside OrganizationSwitcher.');
@@ -96,7 +96,7 @@ export const useOrganizationSwitcherContext = () => {
return {
...ctx,
- hidePersonal: ctx.hidePersonal || false,
+ hidePersonal: organizationSettings.forceOrganizationSelection || ctx.hidePersonal || false,
organizationProfileMode: organizationProfileMode || 'modal',
createOrganizationMode: createOrganizationMode || 'modal',
skipInvitationScreen: ctx.skipInvitationScreen || false,
diff --git a/packages/clerk-js/src/ui/utils/test/fixtureHelpers.ts b/packages/clerk-js/src/ui/utils/test/fixtureHelpers.ts
index 20d0244c7b2..b7cb2c1ea2b 100644
--- a/packages/clerk-js/src/ui/utils/test/fixtureHelpers.ts
+++ b/packages/clerk-js/src/ui/utils/test/fixtureHelpers.ts
@@ -317,13 +317,16 @@ const createOrganizationSettingsFixtureHelpers = (environment: EnvironmentJSON)
const withMaxAllowedMemberships = ({ max = 5 }) => {
os.max_allowed_memberships = max;
};
+ const withForceOrganizationSelection = () => {
+ os.force_organization_selection = true;
+ };
const withOrganizationDomains = (modes?: OrganizationEnrollmentMode[], defaultRole?: string) => {
os.domains.enabled = true;
os.domains.enrollment_modes = modes || ['automatic_invitation', 'automatic_invitation', 'manual_invitation'];
os.domains.default_role = defaultRole ?? null;
};
- return { withOrganizations, withMaxAllowedMemberships, withOrganizationDomains };
+ return { withOrganizations, withMaxAllowedMemberships, withOrganizationDomains, withForceOrganizationSelection };
};
const createUserSettingsFixtureHelpers = (environment: EnvironmentJSON) => {
diff --git a/packages/clerk-js/src/ui/utils/test/fixtures.ts b/packages/clerk-js/src/ui/utils/test/fixtures.ts
index a7cf180205f..9eb97488214 100644
--- a/packages/clerk-js/src/ui/utils/test/fixtures.ts
+++ b/packages/clerk-js/src/ui/utils/test/fixtures.ts
@@ -82,6 +82,7 @@ const createBaseOrganizationSettings = (): OrganizationSettingsJSON => {
return {
enabled: false,
max_allowed_memberships: 5,
+ force_organization_selection: false,
domains: {
enabled: false,
enrollment_modes: [],
diff --git a/packages/types/src/organizationSettings.ts b/packages/types/src/organizationSettings.ts
index 0e5041508c4..afbe09c5c97 100644
--- a/packages/types/src/organizationSettings.ts
+++ b/packages/types/src/organizationSettings.ts
@@ -8,6 +8,7 @@ export interface OrganizationSettingsJSON extends ClerkResourceJSON {
object: never;
enabled: boolean;
max_allowed_memberships: number;
+ force_organization_selection: boolean;
actions: {
admin_delete: boolean;
};
@@ -21,6 +22,7 @@ export interface OrganizationSettingsJSON extends ClerkResourceJSON {
export interface OrganizationSettingsResource extends ClerkResource {
enabled: boolean;
maxAllowedMemberships: number;
+ forceOrganizationSelection: boolean;
actions: {
adminDelete: boolean;
};