Skip to content

Commit 2e35ac5

Browse files
authoredSep 26, 2024··
feat(clerk-js,types,localizations): Render "Restricted access" screen for restricted signup mode (#4220)
1 parent f1f17ea commit 2e35ac5

File tree

9 files changed

+108
-2
lines changed

9 files changed

+108
-2
lines changed
 

‎.changeset/warm-points-accept.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@clerk/localizations": minor
3+
"@clerk/clerk-js": minor
4+
"@clerk/types": minor
5+
---
6+
7+
Render "Restricted access" screen in `<SignUp />` component when `signup.mode` in `userSettings` is `restricted`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { useClerk } from '@clerk/shared/react';
2+
3+
import { useSignUpContext } from '../../contexts';
4+
import { Icon, localizationKeys } from '../../customizables';
5+
import { Card, Header } from '../../elements';
6+
import { useCardState } from '../../elements/contexts';
7+
import { Block } from '../../icons';
8+
export const SignUpRestrictedAccess = () => {
9+
const clerk = useClerk();
10+
const card = useCardState();
11+
const { signInUrl } = useSignUpContext();
12+
13+
return (
14+
<Card.Root>
15+
<Card.Content>
16+
<Header.Root showLogo>
17+
<Icon
18+
icon={Block}
19+
sx={t => ({
20+
margin: 'auto',
21+
width: t.sizes.$12,
22+
height: t.sizes.$12,
23+
})}
24+
/>
25+
<Header.Title localizationKey={localizationKeys('signUp.restrictedAccess.title')} />
26+
<Header.Subtitle localizationKey={localizationKeys('signUp.restrictedAccess.subtitle')} />
27+
</Header.Root>
28+
<Card.Alert>{card.error}</Card.Alert>
29+
<Card.Action elementId='signUp'>
30+
<Card.ActionLink
31+
localizationKey={localizationKeys('signUp.restrictedAccess.actionLink')}
32+
to={clerk.buildUrlWithAuth(signInUrl)}
33+
/>
34+
</Card.Action>
35+
</Card.Content>
36+
<Card.Footer />
37+
</Card.Root>
38+
);
39+
};

‎packages/clerk-js/src/ui/components/SignUp/SignUpStart.tsx

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useClerk } from '@clerk/shared/react';
22
import React from 'react';
33

4-
import { ERROR_CODES } from '../../../core/constants';
4+
import { ERROR_CODES, SIGN_UP_MODES } from '../../../core/constants';
55
import { getClerkQueryParam, removeClerkQueryParam } from '../../../utils/getClerkQueryParam';
66
import { buildSSOCallbackURL, withRedirectToAfterSignUp } from '../../common';
77
import { useCoreSignUp, useEnvironment, useSignUpContext } from '../../contexts';
@@ -22,6 +22,7 @@ import { buildRequest, createPasswordError, handleError, useFormControl } from '
2222
import { SignUpForm } from './SignUpForm';
2323
import type { ActiveIdentifier } from './signUpFormHelpers';
2424
import { determineActiveFields, emailOrPhone, getInitialActiveIdentifier, showFormFields } from './signUpFormHelpers';
25+
import { SignUpRestrictedAccess } from './SignUpRestrictedAccess';
2526
import { SignUpSocialButtons } from './SignUpSocialButtons';
2627
import { completeSignUpFlow } from './util';
2728

@@ -49,6 +50,8 @@ function _SignUpStart(): JSX.Element {
4950
userSettings: { passwordSettings },
5051
} = useEnvironment();
5152

53+
const { mode } = userSettings.signUp;
54+
5255
const formState = {
5356
firstName: useFormControl('firstName', signUp.firstName || initialValues.firstName || '', {
5457
type: 'text',
@@ -246,6 +249,10 @@ function _SignUpStart(): JSX.Element {
246249
(!hasTicket || missingRequirementsWithTicket) && userSettings.authenticatableSocialStrategies.length > 0;
247250
const showWeb3Providers = !hasTicket && userSettings.web3FirstFactors.length > 0;
248251

252+
if (mode === SIGN_UP_MODES.RESTRICTED && !hasTicket) {
253+
return <SignUpRestrictedAccess />;
254+
}
255+
249256
return (
250257
<Flow.Part part='start'>
251258
<Card.Root>

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

+38
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,17 @@ describe('SignUpStart', () => {
245245
});
246246
});
247247

248+
describe('Restricted signup', () => {
249+
it('shows the restricted component', async () => {
250+
const { wrapper } = await createFixtures(f => {
251+
f.withRestrictedMode();
252+
});
253+
254+
render(<SignUpStart />, { wrapper });
255+
screen.getByText('Restricted access');
256+
});
257+
});
258+
248259
describe('ticket flow', () => {
249260
it('calls the appropriate resource function upon detecting the ticket', async () => {
250261
const { wrapper, fixtures } = await createFixtures(f => {
@@ -319,5 +330,32 @@ describe('SignUpStart', () => {
319330
expect.not.stringContaining('__clerk_invitation_token'),
320331
);
321332
});
333+
334+
it('should show the sign up form when ticket detected and mode is restricted', async () => {
335+
const { wrapper, fixtures } = await createFixtures(f => {
336+
f.withEmailAddress();
337+
f.withPassword();
338+
f.withRestrictedMode();
339+
});
340+
fixtures.signUp.create.mockResolvedValueOnce({} as SignUpResource);
341+
342+
Object.defineProperty(window, 'location', {
343+
writable: true,
344+
value: { href: 'http://localhost/sign-up?__clerk_ticket=test_ticket' },
345+
});
346+
Object.defineProperty(window, 'history', {
347+
writable: true,
348+
value: { replaceState: jest.fn() },
349+
});
350+
351+
render(
352+
<CardStateProvider>
353+
<SignUpStart />
354+
</CardStateProvider>,
355+
{ wrapper },
356+
);
357+
358+
await waitFor(() => screen.getByText(/create your account/i));
359+
});
322360
});
323361
});
+1
Loading

‎packages/clerk-js/src/ui/icons/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,4 @@ export { default as CaretRight } from './caret-right.svg';
6161
export { default as Organization } from './organization.svg';
6262
export { default as Users } from './users.svg';
6363
export { default as Fingerprint } from './fingerprint.svg';
64+
export { default as Block } from './block.svg';

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,10 @@ const createUserSettingsFixtureHelpers = (environment: EnvironmentJSON) => {
319319
show_zxcvbn: false,
320320
min_zxcvbn_strength: 0,
321321
};
322-
us.sign_up.mode = SIGN_UP_MODES.PUBLIC;
322+
us.sign_up = {
323+
...us.sign_up,
324+
mode: SIGN_UP_MODES.PUBLIC,
325+
};
323326

324327
const emptyAttribute = {
325328
first_factors: [],

‎packages/localizations/src/en-US.ts

+5
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,11 @@ export const enUS: LocalizationResource = {
508508
subtitle: 'Welcome! Please fill in the details to get started.',
509509
title: 'Create your account',
510510
},
511+
restrictedAccess: {
512+
title: 'Restricted access',
513+
subtitle: 'Access to this app is limited, and an invitation is required to sign up.',
514+
actionLink: 'Back to sign in',
515+
},
511516
},
512517
socialButtonsBlockButton: 'Continue with {{provider|titleize}}',
513518
socialButtonsBlockButtonManyInView: '{{provider|titleize}}',

‎packages/types/src/localization.ts

+5
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@ type _LocalizationResource = {
144144
actionText: LocalizationValue;
145145
actionLink: LocalizationValue;
146146
};
147+
restrictedAccess: {
148+
title: LocalizationValue;
149+
subtitle: LocalizationValue;
150+
actionLink: LocalizationValue;
151+
};
147152
};
148153
signIn: {
149154
start: {

0 commit comments

Comments
 (0)
Please sign in to comment.