Skip to content

Commit bb1e4e2

Browse files
committed
Add isCompleted prop to step
1 parent 78d6cc4 commit bb1e4e2

7 files changed

Lines changed: 40 additions & 13 deletions

File tree

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1459,7 +1459,7 @@ export class Clerk implements ClerkInterface {
14591459

14601460
if (noUserExists(this)) {
14611461
if (this.#instanceType === 'development') {
1462-
throw new ClerkRuntimeError(warnings.cannotOpenCheckout, {
1462+
throw new ClerkRuntimeError(warnings.cannotRenderConfigureSSOComponentWhenUserDoesNotExist, {
14631463
code: CANNOT_RENDER_USER_MISSING_ERROR_CODE,
14641464
});
14651465
}

packages/shared/src/internal/clerk-js/warnings.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ const warnings = {
6464
'The <APIKeys/> component cannot be rendered when organization API keys are disabled. Since organization API keys are disabled, this is no-op.',
6565
cannotRenderOAuthConsentComponentWhenUserDoesNotExist:
6666
'<OAuthConsent/> cannot render unless a user is signed in. Since no user is signed in, this is no-op.',
67+
cannotRenderConfigureSSOComponentWhenUserDoesNotExist:
68+
'<ConfigureSSO/> cannot render unless a user is signed in. Since no user is signed in, this is no-op.',
6769
cannotRenderConfigureSSOComponentWhenDisabled:
6870
'The <ConfigureSSO/> component cannot be rendered when self-serve SSO is disabled. Visit `https://dashboard.clerk.com` to enable the feature. Since self-serve SSO is disabled, this is no-op.',
6971
cannotRenderConfigureSSOComponentWhenEmailAddressDisabled:

packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { BoxIcon } from '@/icons';
1212
import { Route, Switch } from '@/router';
1313

1414
import { ConfigureSSOFlowProvider } from './ConfigureSSOContext';
15-
import { ConfigureCreateApp, ConfirmationStep, ProvideEmail, TestConfigurationStep, VerifyDomain } from './steps';
15+
import { ConfigureCreateApp, ConfirmationStep, ProvideEmail, TestConfigurationStep, VerifyDomainStep } from './steps';
1616
import { ConfigureSSOWizard } from './wizard';
1717

1818
const ConfigureSSOInternal = () => {
@@ -127,6 +127,7 @@ const AuthenticatedContent = withCoreUserGuard(() => {
127127

128128
const ConfigureSSOSteps = () => {
129129
const { user } = useUser();
130+
130131
const primaryEmailAddress = user?.primaryEmailAddress;
131132

132133
return (
@@ -149,7 +150,7 @@ const ConfigureSSOSteps = () => {
149150
id='verify-domain'
150151
path='verify-domain'
151152
>
152-
<VerifyDomain />
153+
<VerifyDomainStep />
153154
</ConfigureSSOWizard.Step>
154155
</ConfigureSSOWizard>
155156
</ConfigureSSOWizard.Step>

packages/ui/src/components/ConfigureSSO/steps/VerifyDomainStep.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ import { Flow, Text } from '@/customizables';
33
import { useConfigureSSOWizard, useRegisterContinueAction } from '../wizard';
44
import { StepLayout } from './StepLayout';
55

6-
export const VerifyDomain = (): JSX.Element => {
6+
export const VerifyDomainStep = (): JSX.Element => {
77
const { goNext } = useConfigureSSOWizard();
88

99
useRegisterContinueAction({
1010
handler: () => goNext(),
11+
// TODO: Implement verification
12+
isDisabled: true,
1113
});
1214

1315
return (

packages/ui/src/components/ConfigureSSO/steps/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ export { ConfirmationStep } from './ConfirmationStep';
33
export { ProvideEmail } from './ProvideEmailStep';
44
export { StepLayout } from './StepLayout';
55
export { TestConfigurationStep } from './TestConfigurationStep';
6-
export { VerifyDomain } from './VerifyDomainStep';
6+
export { VerifyDomainStep } from './VerifyDomainStep';

packages/ui/src/components/ConfigureSSO/wizard/ConfigureSSOWizard.tsx

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22

33
import { Badge, Box, Button, Col, descriptors, Flex, Icon, Spinner, Text, useLocalizations } from '@/customizables';
4-
import { CaretLeft, CaretRight } from '@/icons';
4+
import { CaretLeft, CaretRight, Check } from '@/icons';
55
import { Route, Switch, useRouter } from '@/router';
66

77
import { useConfigureSSOFlow } from '../ConfigureSSOContext';
@@ -54,6 +54,7 @@ function extractSteps(children: React.ReactNode): ConfigureSSOWizardActiveStep[]
5454
id: props.id,
5555
path: props.path,
5656
label: props.label,
57+
isCompleted: props.isCompleted,
5758
children: props.children,
5859
});
5960
});
@@ -177,8 +178,8 @@ const RootInner = ({ parentWizard, isNested, children }: RootInnerProps): JSX.El
177178
goPrev,
178179
goToStep,
179180
isNested,
180-
isFirstStep: index <= 0 && !parentWizard,
181-
isLastStep: index === activeSteps.length - 1 && !parentWizard,
181+
isFirstStep: index <= 0 && (!parentWizard || parentWizard.isFirstStep),
182+
isLastStep: index === activeSteps.length - 1 && (!parentWizard || parentWizard.isLastStep),
182183
};
183184
}, [activeSteps, currentStep, isLoading, goNext, goPrev, goToStep, isNested, parentWizard]);
184185

@@ -285,8 +286,8 @@ const Header = (): JSX.Element => {
285286
>
286287
{activeSteps.map((step, index) => {
287288
const isCurrent = index === currentIndex;
288-
const isCompleted = index < currentIndex;
289-
const isReachable = index <= currentIndex;
289+
const isCompleted = step.isCompleted ?? index < currentIndex;
290+
const isReachable = isCompleted || index <= currentIndex;
290291
const labelText = step.label ? (typeof step.label === 'string' ? step.label : t(step.label)) : '';
291292

292293
return (
@@ -326,12 +327,23 @@ const Header = (): JSX.Element => {
326327
backgroundColor: isCurrent
327328
? theme.colors.$colorForeground
328329
: isCompleted
329-
? theme.colors.$neutralAlpha200
330+
? theme.colors.$success500
330331
: theme.colors.$neutralAlpha100,
331-
color: isCurrent ? theme.colors.$colorBackground : theme.colors.$colorMutedForeground,
332+
color: isCurrent
333+
? theme.colors.$colorBackground
334+
: isCompleted
335+
? theme.colors.$white
336+
: theme.colors.$colorMutedForeground,
332337
})}
333338
>
334-
{index + 1}
339+
{isCompleted && !isCurrent ? (
340+
<Icon
341+
icon={Check}
342+
size='xs'
343+
/>
344+
) : (
345+
index + 1
346+
)}
335347
</Flex>
336348
<Text
337349
elementDescriptor={descriptors.configureSSOWizardHeaderItemLabel}

packages/ui/src/components/ConfigureSSO/wizard/types.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ export interface ConfigureSSOWizardStepProps {
2626
* breadcrumb entry
2727
*/
2828
label?: LocalizationKey | string;
29+
/**
30+
* Marks this step as completed regardless of its position relative
31+
* to the current step. Completed steps are styled as such in the
32+
* breadcrumb and remain reachable via `goToStep`. Useful when a
33+
* downstream step's data already exists (e.g. the resource was
34+
* created in a previous session) and the user can revisit earlier
35+
* steps without "uncompleting" later ones
36+
*/
37+
isCompleted?: boolean;
2938
/**
3039
* The step body. Anything React, including a nested
3140
* `<ConfigureSSOWizard>` for inner sub-steps
@@ -68,6 +77,7 @@ export interface ConfigureSSOWizardActiveStep {
6877
id: string;
6978
path: string;
7079
label?: LocalizationKey | string;
80+
isCompleted?: boolean;
7181
children: React.ReactNode;
7282
}
7383

0 commit comments

Comments
 (0)