Skip to content

Commit

Permalink
fix(clerk-js): Redirect to current page within modal with no redirect…
Browse files Browse the repository at this point in the history
… url (#4768)
  • Loading branch information
alexcarpenter authored Dec 16, 2024
1 parent 5286884 commit 2de7ac4
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/young-swans-sin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@clerk/clerk-js': minor
---

Redirect to the current page when within modal mode and no redirect URL is provided.
1 change: 1 addition & 0 deletions packages/clerk-js/src/ui/components/SignIn/SignIn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ export const SignInModal = (props: SignInModalProps): JSX.Element => {
componentName: 'SignIn',
...signInProps,
routing: 'virtual',
mode: 'modal',
}}
>
{/*TODO: Used by InvisibleRootBox, can we simplify? */}
Expand Down
1 change: 1 addition & 0 deletions packages/clerk-js/src/ui/components/SignUp/SignUp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export const SignUpModal = (props: SignUpModalProps): JSX.Element => {
componentName: 'SignUp',
...signUpProps,
routing: 'virtual',
mode: 'modal',
}}
>
{/*TODO: Used by InvisibleRootBox, can we simplify? */}
Expand Down
3 changes: 2 additions & 1 deletion packages/clerk-js/src/ui/contexts/components/SignIn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const useSignInContext = (): SignInContextType => {
throw new Error(`Clerk: useSignInContext called outside of the mounted SignIn component.`);
}

const { componentName, ..._ctx } = context;
const { componentName, mode, ..._ctx } = context;
const ctx = _ctx.__experimental?.combinedProps || _ctx;

const initialValuesFromQueryParams = useMemo(
Expand All @@ -53,6 +53,7 @@ export const useSignInContext = (): SignInContextType => {
signInForceRedirectUrl: ctx.forceRedirectUrl,
},
queryParams,
mode,
);

const afterSignInUrl = clerk.buildUrlWithAuth(redirectUrls.getAfterSignInUrl());
Expand Down
3 changes: 2 additions & 1 deletion packages/clerk-js/src/ui/contexts/components/SignUp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const useSignUpContext = (): SignUpContextType => {
throw new Error('Clerk: useSignUpContext called outside of the mounted SignUp component.');
}

const { componentName, ...ctx } = context;
const { componentName, mode, ...ctx } = context;

const redirectUrls = new RedirectUrls(
options,
Expand All @@ -51,6 +51,7 @@ export const useSignUpContext = (): SignUpContextType => {
signUpForceRedirectUrl: ctx.forceRedirectUrl,
},
queryParams,
mode,
);

const afterSignUpUrl = clerk.buildUrlWithAuth(redirectUrls.getAfterSignUpUrl());
Expand Down
15 changes: 15 additions & 0 deletions packages/clerk-js/src/utils/__tests__/redirectUrls.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,21 @@ describe('redirectUrls', () => {
expect(redirectUrls.getAfterSignInUrl()).toBe(`${mockWindowLocation.href}search-param-redirect-url`);
expect(redirectUrls.getAfterSignUpUrl()).toBe(`${mockWindowLocation.href}search-param-redirect-url`);
});

it('returns to `/` when no redirect_url is found', () => {
const redirectUrls = new RedirectUrls({}, {}, {});
expect(redirectUrls.getAfterSignInUrl()).toBe('/');
expect(redirectUrls.getAfterSignUpUrl()).toBe('/');
});

it('returns current window location when in modal mode and no redirect_url is found', () => {
const aboutPageUrl = 'https://www.clerk.com/about';
mockWindowLocation = new URL(aboutPageUrl) as any as Window['location'];
Object.defineProperty(global.window, 'location', { value: mockWindowLocation });
const redirectUrls = new RedirectUrls({}, {}, {}, 'modal');
expect(redirectUrls.getAfterSignInUrl()).toBe(aboutPageUrl);
expect(redirectUrls.getAfterSignUpUrl()).toBe(aboutPageUrl);
});
});

describe('search params', () => {
Expand Down
10 changes: 9 additions & 1 deletion packages/clerk-js/src/utils/redirectUrls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import type { ClerkOptions, RedirectOptions } from '@clerk/types';
import { assertNoLegacyProp, warnForNewPropShadowingLegacyProp } from './assertNoLegacyProp';
import { isAllowedRedirect, relativeToAbsoluteUrl } from './url';

type ComponentMode = 'modal' | 'mounted';

export class RedirectUrls {
private static keys: (keyof RedirectOptions)[] = [
'signInForceRedirectUrl',
Expand All @@ -22,12 +24,14 @@ export class RedirectUrls {
private readonly fromOptions: RedirectOptions;
private readonly fromProps: RedirectOptions;
private readonly fromSearchParams: RedirectOptions & { redirectUrl?: string | null };
private readonly mode?: ComponentMode;

constructor(options: ClerkOptions, props: RedirectOptions = {}, searchParams: any = {}) {
constructor(options: ClerkOptions, props: RedirectOptions = {}, searchParams: any = {}, mode?: ComponentMode) {
this.options = options;
this.fromOptions = this.#parse(options || {});
this.fromProps = this.#parse(props || {});
this.fromSearchParams = this.#parseSearchParams(searchParams || {});
this.mode = mode;
}

getAfterSignInUrl() {
Expand Down Expand Up @@ -136,6 +140,10 @@ export class RedirectUrls {
warnForNewPropShadowingLegacyProp(newKeyInUse, result, legacyPropKey, legacyValue);
result ||= legacyValue;

if (!result && this.mode === 'modal') {
return window.location.href;
}

return result || '/';
}

Expand Down

0 comments on commit 2de7ac4

Please sign in to comment.