Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
8b34b1f
Run `pnpm dedupe`
LauraBeatris Nov 3, 2025
801896c
Add HOC to open modal based on org settings
LauraBeatris Nov 5, 2025
ecbd68c
Replace throwing error with opening modal
LauraBeatris Nov 5, 2025
568a0e1
Move to shared styles
LauraBeatris Nov 7, 2025
c30eb02
Revert pnpm-lock.yaml changes
LauraBeatris Nov 10, 2025
a7a6f29
Update `PromptContainer` to exclude keyless styles
LauraBeatris Nov 11, 2025
243034b
Fix line height and use monospace font
LauraBeatris Nov 11, 2025
3eeb8a8
Introduce mutation to enable organization settings
LauraBeatris Nov 11, 2025
277b3e7
Mount components once mutation is resolved
LauraBeatris Nov 11, 2025
9dd7ba6
Introduce draft for enabled prompt state
LauraBeatris Nov 12, 2025
8d491bb
Extract button to generic component
LauraBeatris Nov 12, 2025
3d486f4
Extract button to generic component
LauraBeatris Nov 12, 2025
e393658
Always throw error when rejecting prompt
LauraBeatris Nov 12, 2025
3d9acfd
Adjust focus and hover styles
LauraBeatris Nov 12, 2025
946fc8c
Extract Dashboard URL to display within anchor tag
LauraBeatris Nov 12, 2025
e76a077
Bump bundlewatch
LauraBeatris Nov 13, 2025
213a899
Add separate chunk on bundlwatch
LauraBeatris Nov 13, 2025
ab6f3ac
Refactor UI to include personal account toogle
LauraBeatris Nov 13, 2025
7bc4a50
Add changeset
LauraBeatris Nov 13, 2025
80bc16f
Send default value for `allow_personal_account` option
LauraBeatris Nov 17, 2025
abbcc55
Adjust bundlwatch
LauraBeatris Nov 17, 2025
178f4da
Show warning if there is not an active session
LauraBeatris Nov 18, 2025
492efb8
feat: Add support for `initialFocusRef` (#7247)
alexcarpenter Nov 18, 2025
eb1d82b
refactor: Button variant improvements (#7249)
alexcarpenter Nov 18, 2025
9072380
Fix `dev_tools` endpoint
LauraBeatris Nov 18, 2025
e32827c
Display prompt even without session
LauraBeatris Nov 18, 2025
7725a4b
refactor: Switch improvements (#7253)
alexcarpenter Nov 18, 2025
a39fa8a
Fix `EnableEnvironmentSettingParams`
LauraBeatris Nov 18, 2025
9385228
Add a "sign-in to continue" button when unauthenticated
LauraBeatris Nov 18, 2025
edf8fc2
Fix isomorphic clerk types
LauraBeatris Nov 18, 2025
fffde5c
Continue to display personal account toggle regardless of session
LauraBeatris Nov 19, 2025
f340279
update switch color
alexcarpenter Nov 19, 2025
ab3745f
Use `useOrganizationContext` in `useCheckout`
LauraBeatris Nov 19, 2025
91d0989
Conditionally display personal accounts toggle based on environment
LauraBeatris Nov 19, 2025
d25fd91
Fix check for `forceOrganizationSelection`
LauraBeatris Nov 19, 2025
80519b7
Conditionally send `organization_allow_personal_accounts` param
LauraBeatris Nov 19, 2025
5c2d792
Update `organization_allow_personal_accounts` to optional
LauraBeatris Nov 19, 2025
c0a24dd
Fix import for `@emotion/react`
LauraBeatris Nov 19, 2025
7c410d6
feat: animate height of switch (#7263)
alexcarpenter Nov 19, 2025
085f193
Use `useOrganizationContext` in `APIKeys`
LauraBeatris Nov 19, 2025
c4e3104
Update copy
LauraBeatris Nov 19, 2025
8824ffc
Display Clerk icon with animation
LauraBeatris Nov 19, 2025
3bd6587
Update mock on commerce unit tests
LauraBeatris Nov 20, 2025
61e3dc1
Adjust vue composable to execute when Clerk is loaded
LauraBeatris Nov 20, 2025
be7d8a9
Safely execute prompt guard within hooks
LauraBeatris Nov 20, 2025
07b869e
Use `pnpm` for nuxt integration test script
LauraBeatris Nov 20, 2025
42fdc39
Rollback publishable key changes from sandbox
LauraBeatris Nov 20, 2025
f500065
Attempt to fix Nuxt errors
LauraBeatris Nov 20, 2025
f9bac75
Hydrate preopenEnableOrganizationsPrompt
LauraBeatris Nov 21, 2025
e763d6e
feat: Coin flip animation
alexcarpenter Nov 20, 2025
87dd600
Add comments to clarify optional chaining
LauraBeatris Nov 21, 2025
7f359b3
Fix Dashboard link
LauraBeatris Nov 21, 2025
9c5e8fc
Fix Dashboard URL
LauraBeatris Nov 21, 2025
7cec59b
Include unit tests
LauraBeatris Nov 24, 2025
2da34a0
Remove unused mock
LauraBeatris Nov 24, 2025
e3da555
Update bundlwatch
LauraBeatris Nov 24, 2025
21d53a9
Use logger singleton
LauraBeatris Nov 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changeset/flat-ravens-call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@clerk/clerk-js': minor
'@clerk/shared': minor
'@clerk/clerk-react': minor
'@clerk/vue': minor
---

Introduce in-app development prompt to enable the Organizations feature

In development instances, when using organization components or hooks for the first time, developers will see a prompt to enable the Organizations feature directly in their app, eliminating the need to visit the Clerk Dashboard.
9 changes: 5 additions & 4 deletions packages/clerk-js/bundlewatch.config.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"files": [
{ "path": "./dist/clerk.js", "maxSize": "840KB" },
{ "path": "./dist/clerk.browser.js", "maxSize": "81KB" },
{ "path": "./dist/clerk.channel.browser.js", "maxSize": "81KB" },
{ "path": "./dist/clerk.legacy.browser.js", "maxSize": "123KB" },
{ "path": "./dist/clerk.browser.js", "maxSize": "83KB" },
{ "path": "./dist/clerk.channel.browser.js", "maxSize": "83KB" },
{ "path": "./dist/clerk.legacy.browser.js", "maxSize": "127KB" },
{ "path": "./dist/clerk.headless*.js", "maxSize": "65KB" },
{ "path": "./dist/ui-common*.js", "maxSize": "117.1KB" },
{ "path": "./dist/ui-common*.js", "maxSize": "119KB" },
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "122KB" },
{ "path": "./dist/vendors*.js", "maxSize": "47KB" },
{ "path": "./dist/coinbase*.js", "maxSize": "38KB" },
Expand All @@ -23,6 +23,7 @@
{ "path": "./dist/onetap*.js", "maxSize": "1KB" },
{ "path": "./dist/waitlist*.js", "maxSize": "1.5KB" },
{ "path": "./dist/keylessPrompt*.js", "maxSize": "6.5KB" },
{ "path": "./dist/enableOrganizationsPrompt*.js", "maxSize": "6.5KB" },
{ "path": "./dist/pricingTable*.js", "maxSize": "4.02KB" },
{ "path": "./dist/checkout*.js", "maxSize": "8.82KB" },
{ "path": "./dist/up-billing-page*.js", "maxSize": "3.0KB" },
Expand Down
124 changes: 124 additions & 0 deletions packages/clerk-js/src/core/__tests__/clerk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2508,4 +2508,128 @@ describe('Clerk singleton', () => {
});
});
});

describe('__internal_attemptToEnableEnvironmentSetting', () => {
describe('for organizations', () => {
it('does not open prompt if organizations is enabled in development', async () => {
mockEnvironmentFetch.mockReturnValue(
Promise.resolve({
userSettings: mockUserSettings,
displayConfig: mockDisplayConfig,
isSingleSession: () => false,
isProduction: () => false,
isDevelopmentOrStaging: () => true,
organizationSettings: {
enabled: true,
},
}),
);

const sut = new Clerk(productionPublishableKey);

const __internal_openEnableOrganizationsPromptSpy = vi.fn();
sut.__internal_openEnableOrganizationsPrompt = __internal_openEnableOrganizationsPromptSpy;

await sut.load();

const result = await sut.__internal_attemptToEnableEnvironmentSetting({
for: 'organizations',
caller: 'OrganizationSwitcher',
});

expect(result?.isEnabled).toBe(true);
expect(__internal_openEnableOrganizationsPromptSpy).not.toHaveBeenCalled();
});

it('does not open prompt if organizations is enabled in production', async () => {
mockEnvironmentFetch.mockReturnValue(
Promise.resolve({
userSettings: mockUserSettings,
displayConfig: mockDisplayConfig,
isSingleSession: () => false,
isProduction: () => true,
isDevelopmentOrStaging: () => true,
organizationSettings: {
enabled: true,
},
}),
);

const sut = new Clerk(productionPublishableKey);

const __internal_openEnableOrganizationsPromptSpy = vi.fn();
sut.__internal_openEnableOrganizationsPrompt = __internal_openEnableOrganizationsPromptSpy;

await sut.load();

const result = await sut.__internal_attemptToEnableEnvironmentSetting({
for: 'organizations',
caller: 'OrganizationSwitcher',
});

expect(result?.isEnabled).toBe(true);
expect(__internal_openEnableOrganizationsPromptSpy).not.toHaveBeenCalled();
});

it('opens prompt if organizations is disabled in development', async () => {
mockEnvironmentFetch.mockReturnValue(
Promise.resolve({
userSettings: mockUserSettings,
displayConfig: mockDisplayConfig,
isSingleSession: () => false,
isProduction: () => false,
isDevelopmentOrStaging: () => true,
organizationSettings: {
enabled: false,
},
}),
);

const sut = new Clerk(developmentPublishableKey);

const __internal_openEnableOrganizationsPromptSpy = vi.fn();
sut.__internal_openEnableOrganizationsPrompt = __internal_openEnableOrganizationsPromptSpy;

await sut.load();

const result = await sut.__internal_attemptToEnableEnvironmentSetting({
for: 'organizations',
caller: 'OrganizationSwitcher',
});

expect(result?.isEnabled).toBe(false);
expect(__internal_openEnableOrganizationsPromptSpy).toHaveBeenCalled();
});

it('does not open prompt if organizations is disabled in production', async () => {
mockEnvironmentFetch.mockReturnValue(
Promise.resolve({
userSettings: mockUserSettings,
displayConfig: mockDisplayConfig,
isSingleSession: () => false,
isProduction: () => false,
isDevelopmentOrStaging: () => true,
organizationSettings: {
enabled: false,
},
}),
);

const sut = new Clerk(productionPublishableKey);

const __internal_openEnableOrganizationsPromptSpy = vi.fn();
sut.__internal_openEnableOrganizationsPrompt = __internal_openEnableOrganizationsPromptSpy;

await sut.load();

const result = await sut.__internal_attemptToEnableEnvironmentSetting({
for: 'organizations',
caller: 'OrganizationSwitcher',
});

expect(result?.isEnabled).toBe(false);
expect(__internal_openEnableOrganizationsPromptSpy).not.toHaveBeenCalled();
});
});
});
});
Loading
Loading