Skip to content

Commit 39bbc51

Browse files
authoredMar 19, 2025··
chore(clerk-js,types): Hide personal workspace options when organization selection is enforced (#5391)
1 parent 13e3ddc commit 39bbc51

File tree

13 files changed

+73
-9
lines changed

13 files changed

+73
-9
lines changed
 

‎.changeset/fresh-plums-run.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@clerk/clerk-js': patch
3+
'@clerk/types': patch
4+
---
5+
6+
Hide personal workspace options when organization selection is enforced

‎packages/clerk-js/src/core/clerk.ts

+12-2
Original file line numberDiff line numberDiff line change
@@ -829,7 +829,12 @@ export class Clerk implements ClerkInterface {
829829
}),
830830
);
831831

832-
this.telemetry?.record(eventPrebuiltComponentMounted('OrganizationSwitcher', props));
832+
this.telemetry?.record(
833+
eventPrebuiltComponentMounted('OrganizationSwitcher', {
834+
...props,
835+
forceOrganizationSelection: this.environment?.organizationSettings.forceOrganizationSelection,
836+
}),
837+
);
833838
};
834839

835840
public unmountOrganizationSwitcher = (node: HTMLDivElement): void => {
@@ -863,7 +868,12 @@ export class Clerk implements ClerkInterface {
863868
}),
864869
);
865870

866-
this.telemetry?.record(eventPrebuiltComponentMounted('OrganizationList', props));
871+
this.telemetry?.record(
872+
eventPrebuiltComponentMounted('OrganizationList', {
873+
...props,
874+
forceOrganizationSelection: this.environment?.organizationSettings.forceOrganizationSelection,
875+
}),
876+
);
867877
};
868878

869879
public unmountOrganizationList = (node: HTMLDivElement): void => {

‎packages/clerk-js/src/core/resources/OrganizationSettings.ts

+5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export class OrganizationSettings extends BaseResource implements OrganizationSe
2020
};
2121
enabled: boolean = false;
2222
maxAllowedMemberships: number = 1;
23+
forceOrganizationSelection!: boolean;
2324

2425
public constructor(data: OrganizationSettingsJSON | OrganizationSettingsJSONSnapshot | null = null) {
2526
super();
@@ -43,6 +44,10 @@ export class OrganizationSettings extends BaseResource implements OrganizationSe
4344

4445
this.enabled = this.withDefault(data.enabled, this.enabled);
4546
this.maxAllowedMemberships = this.withDefault(data.max_allowed_memberships, this.maxAllowedMemberships);
47+
this.forceOrganizationSelection = this.withDefault(
48+
data.force_organization_selection,
49+
this.forceOrganizationSelection,
50+
);
4651

4752
return this;
4853
}

‎packages/clerk-js/src/core/resources/__tests__/Environment.test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ describe('Environment', () => {
237237
organization_settings: {
238238
enabled: false,
239239
max_allowed_memberships: 5,
240+
force_organization_selection: false,
240241
actions: { admin_delete: true },
241242
domains: { enabled: false, enrollment_modes: [], default_role: null },
242243
},

‎packages/clerk-js/src/core/resources/__tests__/__snapshots__/Environment.test.ts.snap

+1
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,7 @@ Environment {
581581
"enrollmentModes": [],
582582
},
583583
"enabled": false,
584+
"forceOrganizationSelection": false,
584585
"maxAllowedMemberships": 5,
585586
"pathRoot": "",
586587
},

‎packages/clerk-js/src/ui/components/OrganizationList/__tests__/OrganizationList.test.tsx

+18
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,24 @@ describe('OrganizationList', () => {
185185
expect(queryByRole('button', { name: 'Join' })).not.toBeInTheDocument();
186186
});
187187
});
188+
189+
describe('with force organization selection setting on environment', () => {
190+
it('does not show the personal account', async () => {
191+
const { wrapper } = await createFixtures(f => {
192+
f.withOrganizations();
193+
f.withForceOrganizationSelection();
194+
f.withUser({
195+
email_addresses: ['test@clerk.com'],
196+
organization_memberships: [{ name: 'Org1', id: '1', role: 'admin' }],
197+
});
198+
});
199+
const { queryByText } = render(<OrganizationList />, { wrapper });
200+
201+
await waitFor(() => {
202+
expect(queryByText('Personal account')).not.toBeInTheDocument();
203+
});
204+
});
205+
});
188206
});
189207

190208
describe('CreateOrganization', () => {

‎packages/clerk-js/src/ui/components/OrganizationSwitcher/__tests__/OrganizationSwitcher.test.tsx

+13
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,19 @@ describe('OrganizationSwitcher', () => {
4545
expect(queryByText('Personal Workspace')).toBeNull();
4646
expect(getByText('No organization selected')).toBeInTheDocument();
4747
});
48+
49+
describe('with force organization selection setting on environment', () => {
50+
it('does not show the personal workspace', async () => {
51+
const { wrapper } = await createFixtures(f => {
52+
f.withOrganizations();
53+
f.withForceOrganizationSelection();
54+
f.withUser({ email_addresses: ['test@clerk.com'] });
55+
});
56+
const { queryByText, getByRole, userEvent } = render(<OrganizationSwitcher />, { wrapper });
57+
await userEvent.click(getByRole('button'));
58+
expect(queryByText('Personal Workspace')).toBeNull();
59+
});
60+
});
4861
});
4962

5063
describe('OrganizationSwitcherTrigger', () => {

‎packages/clerk-js/src/ui/components/SessionTask/SessionTask.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@ import { OrganizationList } from '../OrganizationList';
77

88
const ContentRegistry: Record<SessionTask['key'], React.ComponentType> = {
99
org: () => (
10-
// TODO - Hide personal workspace within organization list context based on environment
11-
<OrganizationListContext.Provider value={{ componentName: 'OrganizationList', hidePersonal: true }}>
10+
<OrganizationListContext.Provider
11+
value={{
12+
componentName: 'OrganizationList',
13+
skipInvitationScreen: true,
14+
}}
15+
>
1216
<OrganizationList />
1317
</OrganizationListContext.Provider>
1418
),

‎packages/clerk-js/src/ui/contexts/components/OrganizationList.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export const OrganizationListContext = createContext<OrganizationListCtx | null>
1111
export const useOrganizationListContext = () => {
1212
const context = useContext(OrganizationListContext);
1313
const { navigate } = useRouter();
14-
const { displayConfig } = useEnvironment();
14+
const { displayConfig, organizationSettings } = useEnvironment();
1515

1616
if (!context || context.componentName !== 'OrganizationList') {
1717
throw new Error('Clerk: useOrganizationListContext called outside OrganizationList.');
@@ -80,7 +80,7 @@ export const useOrganizationListContext = () => {
8080
afterCreateOrganizationUrl,
8181
skipInvitationScreen: ctx.skipInvitationScreen || false,
8282
hideSlug: ctx.hideSlug || false,
83-
hidePersonal: ctx.hidePersonal || false,
83+
hidePersonal: organizationSettings.forceOrganizationSelection || ctx.hidePersonal || false,
8484
navigateAfterCreateOrganization,
8585
navigateAfterSelectOrganization,
8686
navigateAfterSelectPersonal,

‎packages/clerk-js/src/ui/contexts/components/OrganizationSwitcher.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export const OrganizationSwitcherContext = createContext<OrganizationSwitcherCtx
1111
export const useOrganizationSwitcherContext = () => {
1212
const context = useContext(OrganizationSwitcherContext);
1313
const { navigate } = useRouter();
14-
const { displayConfig } = useEnvironment();
14+
const { displayConfig, organizationSettings } = useEnvironment();
1515

1616
if (!context || context.componentName !== 'OrganizationSwitcher') {
1717
throw new Error('Clerk: useOrganizationSwitcherContext called outside OrganizationSwitcher.');
@@ -96,7 +96,7 @@ export const useOrganizationSwitcherContext = () => {
9696

9797
return {
9898
...ctx,
99-
hidePersonal: ctx.hidePersonal || false,
99+
hidePersonal: organizationSettings.forceOrganizationSelection || ctx.hidePersonal || false,
100100
organizationProfileMode: organizationProfileMode || 'modal',
101101
createOrganizationMode: createOrganizationMode || 'modal',
102102
skipInvitationScreen: ctx.skipInvitationScreen || false,

‎packages/clerk-js/src/ui/utils/test/fixtureHelpers.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -317,13 +317,16 @@ const createOrganizationSettingsFixtureHelpers = (environment: EnvironmentJSON)
317317
const withMaxAllowedMemberships = ({ max = 5 }) => {
318318
os.max_allowed_memberships = max;
319319
};
320+
const withForceOrganizationSelection = () => {
321+
os.force_organization_selection = true;
322+
};
320323

321324
const withOrganizationDomains = (modes?: OrganizationEnrollmentMode[], defaultRole?: string) => {
322325
os.domains.enabled = true;
323326
os.domains.enrollment_modes = modes || ['automatic_invitation', 'automatic_invitation', 'manual_invitation'];
324327
os.domains.default_role = defaultRole ?? null;
325328
};
326-
return { withOrganizations, withMaxAllowedMemberships, withOrganizationDomains };
329+
return { withOrganizations, withMaxAllowedMemberships, withOrganizationDomains, withForceOrganizationSelection };
327330
};
328331

329332
const createUserSettingsFixtureHelpers = (environment: EnvironmentJSON) => {

‎packages/clerk-js/src/ui/utils/test/fixtures.ts

+1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ const createBaseOrganizationSettings = (): OrganizationSettingsJSON => {
8282
return {
8383
enabled: false,
8484
max_allowed_memberships: 5,
85+
force_organization_selection: false,
8586
domains: {
8687
enabled: false,
8788
enrollment_modes: [],

‎packages/types/src/organizationSettings.ts

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export interface OrganizationSettingsJSON extends ClerkResourceJSON {
88
object: never;
99
enabled: boolean;
1010
max_allowed_memberships: number;
11+
force_organization_selection: boolean;
1112
actions: {
1213
admin_delete: boolean;
1314
};
@@ -21,6 +22,7 @@ export interface OrganizationSettingsJSON extends ClerkResourceJSON {
2122
export interface OrganizationSettingsResource extends ClerkResource {
2223
enabled: boolean;
2324
maxAllowedMemberships: number;
25+
forceOrganizationSelection: boolean;
2426
actions: {
2527
adminDelete: boolean;
2628
};

0 commit comments

Comments
 (0)
Please sign in to comment.