feat(ui,shared,localizations): provider selection step for <__experimental_ConfigureSSO />#8503
feat(ui,shared,localizations): provider selection step for <__experimental_ConfigureSSO />#8503iagodahlem wants to merge 26 commits into
<__experimental_ConfigureSSO />#8503Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: 39c4fb9 The changes in this PR will be included in the next version bump. This PR includes changesets to release 20 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
7dc3f44 to
94f83bd
Compare
aec960d to
53bbef8
Compare
53bbef8 to
87dc071
Compare
<__experimental_ConfigureSSO />
| align='start' | ||
| justify='between' | ||
| sx={theme => ({ gap: theme.space.$4 })} | ||
| > | ||
| <Col sx={theme => ({ gap: theme.space.$1x5, minWidth: 0 })}> | ||
| <Col sx={theme => ({ gap: theme.space.$2, minWidth: 0 })}> |
There was a problem hiding this comment.
Updates the badge display on the header.
<__experimental_ConfigureSSO /><__experimental_ConfigureSSO />
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a fully implemented "Select Provider" step for the experimental ConfigureSSO wizard: provider types and localization schema, localized strings across supported locales, a refactored ConfigureSSO context exposing initialStepId/provider/setProvider/createConnection, deriveInitialStep utility and tests, SelectProviderStep UI with ProviderCard and tests, ConfigureSSO wiring updates, small UI tweaks, and a changeset documenting the feature. Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/localizations/src/kk-KZ.ts`:
- Around line 185-198: The selectProviderStep localization object contains
English strings that must be translated to Kazakh; update the
selectProviderStep.title, subtitle, body.title, body.description,
saml.groupLabel, saml.okta, saml.customSaml, and warning in the kk-KZ.ts file to
Kazakh equivalents (or add an agreed temporary fallback translation) so the
locale no longer renders mixed-language UI; ensure you edit the
selectProviderStep object and preserve the same keys and structure.
In `@packages/ui/src/components/ConfigureSSO/__tests__/deriveInitialStep.test.ts`:
- Line 4: The test currently imports the type WizardStepId from
'../deriveInitialStep' but that type is actually exported from '../types';
update the import statement to import deriveInitialStep (function) from
'../deriveInitialStep' and WizardStepId (type) from '../types' so the file
imports "deriveInitialStep" and "WizardStepId" from their correct modules
(locate the current import line that references deriveInitialStep and change the
type import target to '../types').
In `@packages/ui/src/components/ConfigureSSO/ConfigureSSOContext.tsx`:
- Around line 59-76: The createConnectionFetcher function can call
createEnterpriseConnection multiple times before parent state updates because it
only checks the props enterpriseConnection; add an in-flight guard to make it
truly idempotent by introducing a local flag/ref (e.g., isCreatingRef) that is
checked at the start of createConnectionFetcher and set to true before calling
createEnterpriseConnection and cleared in finally, and also ensure you
short-circuit if createEnterpriseConnection returns an existing/duplicate
connection; keep the existing user.primaryEmailAddress and
session.lastActiveOrganizationId logic but use the guard around the
createEnterpriseConnection call (references: createConnectionFetcher,
enterpriseConnection, createEnterpriseConnection, user.primaryEmailAddress,
session.lastActiveOrganizationId).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro
Run ID: e524dd6f-7a5d-4904-9540-5bc12097a0c5
📒 Files selected for processing (60)
.changeset/configure-sso-select-provider-step.mdpackages/localizations/src/ar-SA.tspackages/localizations/src/be-BY.tspackages/localizations/src/bg-BG.tspackages/localizations/src/bn-IN.tspackages/localizations/src/ca-ES.tspackages/localizations/src/cs-CZ.tspackages/localizations/src/da-DK.tspackages/localizations/src/de-DE.tspackages/localizations/src/el-GR.tspackages/localizations/src/en-GB.tspackages/localizations/src/en-US.tspackages/localizations/src/es-CR.tspackages/localizations/src/es-ES.tspackages/localizations/src/es-MX.tspackages/localizations/src/es-UY.tspackages/localizations/src/fa-IR.tspackages/localizations/src/fi-FI.tspackages/localizations/src/fr-FR.tspackages/localizations/src/he-IL.tspackages/localizations/src/hi-IN.tspackages/localizations/src/hr-HR.tspackages/localizations/src/hu-HU.tspackages/localizations/src/id-ID.tspackages/localizations/src/is-IS.tspackages/localizations/src/it-IT.tspackages/localizations/src/ja-JP.tspackages/localizations/src/kk-KZ.tspackages/localizations/src/ko-KR.tspackages/localizations/src/mn-MN.tspackages/localizations/src/ms-MY.tspackages/localizations/src/nb-NO.tspackages/localizations/src/nl-BE.tspackages/localizations/src/nl-NL.tspackages/localizations/src/pl-PL.tspackages/localizations/src/pt-BR.tspackages/localizations/src/pt-PT.tspackages/localizations/src/ro-RO.tspackages/localizations/src/ru-RU.tspackages/localizations/src/sk-SK.tspackages/localizations/src/sr-RS.tspackages/localizations/src/sv-SE.tspackages/localizations/src/ta-IN.tspackages/localizations/src/te-IN.tspackages/localizations/src/th-TH.tspackages/localizations/src/tr-TR.tspackages/localizations/src/uk-UA.tspackages/localizations/src/vi-VN.tspackages/localizations/src/zh-CN.tspackages/localizations/src/zh-TW.tspackages/shared/src/types/localization.tspackages/ui/src/components/ConfigureSSO/ConfigureSSO.tsxpackages/ui/src/components/ConfigureSSO/ConfigureSSOContext.tsxpackages/ui/src/components/ConfigureSSO/__tests__/deriveInitialStep.test.tspackages/ui/src/components/ConfigureSSO/deriveInitialStep.tspackages/ui/src/components/ConfigureSSO/elements/Step.tsxpackages/ui/src/components/ConfigureSSO/steps/ConfigureStep.tsxpackages/ui/src/components/ConfigureSSO/steps/SelectProviderStep.tsxpackages/ui/src/components/ConfigureSSO/steps/__tests__/SelectProviderStep.test.tsxpackages/ui/src/components/ConfigureSSO/types.ts
| selectProviderStep: { | ||
| title: 'Select provider', | ||
| subtitle: 'Select the provider you are going to setup SSO for.', | ||
| body: { | ||
| title: 'Select your identity provider', | ||
| description: "We'll guide you through the detailed setup process next.", | ||
| }, | ||
| saml: { | ||
| groupLabel: 'SAML', | ||
| okta: 'Okta Workforce', | ||
| customSaml: 'Custom SAML Provider', | ||
| }, | ||
| warning: 'Once a provider is selected you cannot change again until the configuration is over', | ||
| }, |
There was a problem hiding this comment.
kk-KZ Select Provider strings are still English.
Line 186 through Line 197 are not localized to Kazakh, so this locale will render mixed-language UI in the new SSO step.
Suggested temporary fallback until Kazakh copy is provided
selectProviderStep: {
- title: 'Select provider',
- subtitle: 'Select the provider you are going to setup SSO for.',
+ title: undefined,
+ subtitle: undefined,
body: {
- title: 'Select your identity provider',
- description: "We'll guide you through the detailed setup process next.",
+ title: undefined,
+ description: undefined,
},
saml: {
groupLabel: 'SAML',
okta: 'Okta Workforce',
- customSaml: 'Custom SAML Provider',
+ customSaml: undefined,
},
- warning: 'Once a provider is selected you cannot change again until the configuration is over',
+ warning: undefined,
},As per coding guidelines, "Confirm that new translations are accurate, contextually appropriate, and match the intent of the original English strings."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/localizations/src/kk-KZ.ts` around lines 185 - 198, The
selectProviderStep localization object contains English strings that must be
translated to Kazakh; update the selectProviderStep.title, subtitle, body.title,
body.description, saml.groupLabel, saml.okta, saml.customSaml, and warning in
the kk-KZ.ts file to Kazakh equivalents (or add an agreed temporary fallback
translation) so the locale no longer renders mixed-language UI; ensure you edit
the selectProviderStep object and preserve the same keys and structure.
6d20749 to
2529d2b
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/localizations/src/ta-IN.ts`:
- Around line 189-202: The new configureSSO.selectProviderStep strings in ta-IN
are still in English; update the selectProviderStep object (keys: title,
subtitle, body.title, body.description, saml.groupLabel, saml.okta,
saml.customSaml, and warning) with accurate Tamil translations that match the
original meanings and UI context (e.g., "Select provider", "Select the provider
you are going to setup SSO for.", "Select your identity provider", "We'll guide
you through the detailed setup process next.", SAML group label, "Okta
Workforce", "Custom SAML Provider", and the warning about not being able to
change provider). Keep phrasing concise and natural for Tamil UI, and verify
translations for tone and clarity before committing.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro
Run ID: e475d23a-a182-4164-af5b-10b95b32aa45
📒 Files selected for processing (60)
.changeset/configure-sso-select-provider-step.mdpackages/localizations/src/ar-SA.tspackages/localizations/src/be-BY.tspackages/localizations/src/bg-BG.tspackages/localizations/src/bn-IN.tspackages/localizations/src/ca-ES.tspackages/localizations/src/cs-CZ.tspackages/localizations/src/da-DK.tspackages/localizations/src/de-DE.tspackages/localizations/src/el-GR.tspackages/localizations/src/en-GB.tspackages/localizations/src/en-US.tspackages/localizations/src/es-CR.tspackages/localizations/src/es-ES.tspackages/localizations/src/es-MX.tspackages/localizations/src/es-UY.tspackages/localizations/src/fa-IR.tspackages/localizations/src/fi-FI.tspackages/localizations/src/fr-FR.tspackages/localizations/src/he-IL.tspackages/localizations/src/hi-IN.tspackages/localizations/src/hr-HR.tspackages/localizations/src/hu-HU.tspackages/localizations/src/id-ID.tspackages/localizations/src/is-IS.tspackages/localizations/src/it-IT.tspackages/localizations/src/ja-JP.tspackages/localizations/src/kk-KZ.tspackages/localizations/src/ko-KR.tspackages/localizations/src/mn-MN.tspackages/localizations/src/ms-MY.tspackages/localizations/src/nb-NO.tspackages/localizations/src/nl-BE.tspackages/localizations/src/nl-NL.tspackages/localizations/src/pl-PL.tspackages/localizations/src/pt-BR.tspackages/localizations/src/pt-PT.tspackages/localizations/src/ro-RO.tspackages/localizations/src/ru-RU.tspackages/localizations/src/sk-SK.tspackages/localizations/src/sr-RS.tspackages/localizations/src/sv-SE.tspackages/localizations/src/ta-IN.tspackages/localizations/src/te-IN.tspackages/localizations/src/th-TH.tspackages/localizations/src/tr-TR.tspackages/localizations/src/uk-UA.tspackages/localizations/src/vi-VN.tspackages/localizations/src/zh-CN.tspackages/localizations/src/zh-TW.tspackages/shared/src/types/localization.tspackages/ui/src/components/ConfigureSSO/ConfigureSSO.tsxpackages/ui/src/components/ConfigureSSO/ConfigureSSOContext.tsxpackages/ui/src/components/ConfigureSSO/__tests__/deriveInitialStep.test.tspackages/ui/src/components/ConfigureSSO/deriveInitialStep.tspackages/ui/src/components/ConfigureSSO/elements/Step.tsxpackages/ui/src/components/ConfigureSSO/steps/ConfigureStep.tsxpackages/ui/src/components/ConfigureSSO/steps/SelectProviderStep.tsxpackages/ui/src/components/ConfigureSSO/steps/__tests__/SelectProviderStep.test.tsxpackages/ui/src/components/ConfigureSSO/types.ts
✅ Files skipped from review due to trivial changes (31)
- packages/localizations/src/bn-IN.ts
- .changeset/configure-sso-select-provider-step.md
- packages/ui/src/components/ConfigureSSO/types.ts
- packages/localizations/src/hr-HR.ts
- packages/localizations/src/es-UY.ts
- packages/localizations/src/ro-RO.ts
- packages/localizations/src/cs-CZ.ts
- packages/localizations/src/is-IS.ts
- packages/localizations/src/be-BY.ts
- packages/localizations/src/en-GB.ts
- packages/localizations/src/bg-BG.ts
- packages/localizations/src/fa-IR.ts
- packages/localizations/src/es-MX.ts
- packages/localizations/src/sr-RS.ts
- packages/localizations/src/mn-MN.ts
- packages/localizations/src/pt-BR.ts
- packages/localizations/src/el-GR.ts
- packages/localizations/src/kk-KZ.ts
- packages/localizations/src/nl-NL.ts
- packages/localizations/src/ms-MY.ts
- packages/localizations/src/sk-SK.ts
- packages/localizations/src/id-ID.ts
- packages/localizations/src/he-IL.ts
- packages/localizations/src/sv-SE.ts
- packages/localizations/src/hu-HU.ts
- packages/localizations/src/te-IN.ts
- packages/localizations/src/pt-PT.ts
- packages/localizations/src/ja-JP.ts
- packages/localizations/src/nb-NO.ts
- packages/localizations/src/da-DK.ts
- packages/localizations/src/hi-IN.ts
🚧 Files skipped from review as they are similar to previous changes (23)
- packages/localizations/src/uk-UA.ts
- packages/localizations/src/ar-SA.ts
- packages/ui/src/components/ConfigureSSO/elements/Step.tsx
- packages/ui/src/components/ConfigureSSO/tests/deriveInitialStep.test.ts
- packages/localizations/src/ru-RU.ts
- packages/ui/src/components/ConfigureSSO/deriveInitialStep.ts
- packages/localizations/src/es-ES.ts
- packages/localizations/src/fr-FR.ts
- packages/ui/src/components/ConfigureSSO/steps/ConfigureStep.tsx
- packages/localizations/src/en-US.ts
- packages/localizations/src/th-TH.ts
- packages/localizations/src/es-CR.ts
- packages/localizations/src/vi-VN.ts
- packages/ui/src/components/ConfigureSSO/steps/SelectProviderStep.tsx
- packages/localizations/src/zh-CN.ts
- packages/localizations/src/nl-BE.ts
- packages/shared/src/types/localization.ts
- packages/localizations/src/tr-TR.ts
- packages/localizations/src/ko-KR.ts
- packages/localizations/src/fi-FI.ts
- packages/ui/src/components/ConfigureSSO/steps/tests/SelectProviderStep.test.tsx
- packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx
- packages/ui/src/components/ConfigureSSO/ConfigureSSOContext.tsx
| selectProviderStep: { | ||
| title: 'Select provider', | ||
| subtitle: 'Select the provider you are going to setup SSO for.', | ||
| body: { | ||
| title: 'Select your identity provider', | ||
| description: "We'll guide you through the detailed setup process next.", | ||
| }, | ||
| saml: { | ||
| groupLabel: 'SAML', | ||
| okta: 'Okta Workforce', | ||
| customSaml: 'Custom SAML Provider', | ||
| }, | ||
| warning: 'Once a provider is selected you cannot change again until the configuration is over', | ||
| }, |
There was a problem hiding this comment.
ta-IN new SSO provider strings are not translated (still English).
Line 190 through Line 201 add configureSSO.selectProviderStep values in English, which causes mixed-language UI in the Tamil locale and leaves the new keys effectively untranslated for ta-IN. Please provide Tamil translations for this block before merge.
As per coding guidelines: “Confirm that new translations are accurate, contextually appropriate, and match the intent of the original English strings” and “If you notice missing translations for new keys, flag them for completion.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/localizations/src/ta-IN.ts` around lines 189 - 202, The new
configureSSO.selectProviderStep strings in ta-IN are still in English; update
the selectProviderStep object (keys: title, subtitle, body.title,
body.description, saml.groupLabel, saml.okta, saml.customSaml, and warning) with
accurate Tamil translations that match the original meanings and UI context
(e.g., "Select provider", "Select the provider you are going to setup SSO for.",
"Select your identity provider", "We'll guide you through the detailed setup
process next.", SAML group label, "Okta Workforce", "Custom SAML Provider", and
the warning about not being able to change provider). Keep phrasing concise and
natural for Tamil UI, and verify translations for tone and clarity before
committing.
@clerk/astro
@clerk/backend
@clerk/chrome-extension
@clerk/clerk-js
@clerk/dev-cli
@clerk/expo
@clerk/expo-passkeys
@clerk/express
@clerk/fastify
@clerk/hono
@clerk/localizations
@clerk/nextjs
@clerk/nuxt
@clerk/react
@clerk/react-router
@clerk/shared
@clerk/tanstack-react-start
@clerk/testing
@clerk/ui
@clerk/upgrade
@clerk/vue
commit: |
…gureSSO Wire every user-visible string in the Select Provider step through @clerk/localizations. Adds a selectProviderStep namespace under __experimental_configureSSO with title, subtitle, body title/description, SAML group label + provider labels, and the lock-in warning. Populates en-US and translates to all ~49 supported locales.
Adds provider/setProvider/clearProvider/createConnection to the flow context so the Select Provider step can persist the chosen provider and create the enterprise connection on Continue. createConnection is wrapped in useReverification and is idempotent — it no-ops when an enterprise connection already exists.
Pure helper that returns the wizard step a user should mount on based on the state of their enterprise connection. No connection lands on Select Provider, an existing connection without SAML IdP metadata lands on Configure, and a fully configured connection lands on Confirmation. Covered by a table-driven unit test.
Wires Wizard.initialStepId via deriveInitialStep so the ConfigureSSO wizard re-mounts on the right step after reload. Renames the local ProviderType ids in Select Provider from 'okta' / 'custom_saml' to the backend values 'saml_okta' / 'saml_custom' so the Continue handler can forward them directly. Continue now sets the provider on the flow context, calls createConnection, and advances the wizard — wrapped in useCardState for loading and error display following the same pattern as Verify Domain.
Mocks the ConfigureSSO flow context so the Continue handler can be verified end-to-end. Asserts setProvider is called with the backend provider id, followed by createConnection, then goNext, and adds coverage for the loading state and the rejection path where the wizard must not advance and the error must surface in the card.
Notes the flow-context extensions, deriveInitialStep helper, and the createConnection-on-Continue behavior so the published changelog matches what the PR actually ships.
Move ProviderType and WizardStepId into a shared types module and lift initialStepId derivation into the flow context so consumers read a single value instead of recomputing it. Replace the flat PROVIDER_OPTIONS list with grouped PROVIDER_GROUPS to support multiple provider categories, switch connection creation to __internal_useUserEnterpriseConnections, and drop the unused clearProvider/goPrev affordances on the Select Provider step.
…ification - createConnection now accepts the provider as a parameter instead of reading it from React state (which was stale within the same tick as setProvider) - Restore the useReverification wrap on createConnection, matching the rest of @clerk/ui's user.* mutation pattern (createEmailAddress, delete, createTOTP, setPrimary, createWeb3Wallet, …) — handles backend session-reverification policy transparently when present, no-ops otherwise
…ureSSO - Hoist the __internal_useUserEnterpriseConnections call to ConfigureSSOCardContent so the provider receives the data and the create mutation as props instead of calling the hook a second time - Drop the unused isLoading from the provider surface; the load gate upstream already consumes it - Rename ConfigureSSOFlowProvider → ConfigureSSOProvider, useConfigureSSOFlow → useConfigureSSO, drop the leftover "Flow" suffix
Pull the enterprise connection from ConfigureSSOContext inside ConfigureStep and render its SAML ACS URL as the single sign-on URL, replacing the placeholder text. Drop the now-unused isLastStep guard from the Select Provider continue button.
Below 30em the SAML provider grid drops to one card per row instead of the cramped two-column layout. Uses the existing mqu.sm breakpoint and swaps the Grid's columns variant for an sx-driven gridTemplateColumns so the responsive override can layer on top.
Drop createConnection from the context surface and the createEnterpriseConnection prop on ConfigureSSOProvider. The provider now only owns shared wizard state (enterpriseConnection, provider, setProvider, initialStepId). Create logic moves into the Select Provider step in a follow-up commit.
…n Select Provider step The Select Provider step now calls __internal_useUserEnterpriseConnections, useUser, and useSession directly, wrapping the create logic with useReverification + useCallback inline. handleContinue's behaviour is unchanged from the caller's perspective. Test mocks updated to stub the underlying hook instead of an injected createConnection.
… step Previously Continue on Select Provider both staged the chosen provider and called `createEnterpriseConnection`. That meant the backend record was created before the user had actually verified ownership of the domain we were going to wire SSO into, which is why we needed an idempotency guard in the first place. Move the create call into Verify Domain's OTP `onResolve`, immediately after `setPrimaryEmailAddress`. By the time we hit that branch the user has verified the email and we've promoted it to primary, so the connection is only created against a confirmed-owned domain. The existing `enterpriseConnection` short-circuit inside `createConnection` keeps the operation idempotent for users who navigate back through the wizard. Select Provider becomes a pure selection step: track local state, call `setProvider`, advance. Trims the `__internal_useUserEnterpriseConnections`, `useReverification`, `useSession`, `useUser`, `useCardState`, and error routing it no longer needs. Tests are pared down to selection + navigation behavior; the previous create-related assertions move out of scope for this step. A follow-up could add a `VerifyDomainStep.test.tsx` covering the new create-on-resolve path. Skipped for this commit.
9ac22ff to
847bbd2
Compare
The previous SimpleButton + aria-pressed implementation had two problems:
- Mutually-exclusive selection is semantically a radio group, not a set of
independent toggle buttons. Native radio semantics give us screen-reader
announcements ("radio, 1 of 2"), arrow-key navigation between options,
and exclusive-selection guarantees from the browser — none of which the
button pattern provided.
- The selected-state boxShadow was rendered via React state, but
SimpleButton's own :focus / :not(:focus) styles override boxShadow on
every state change. Clicking the card briefly showed the ring (focused
+ checked), but clicking elsewhere cleared focus and the button's
non-focus state took over, wiping the ring even though React state still
said the card was selected.
Refactor to a visually-hidden <input type="radio"> inside a <label> styled
as the card. The label uses :has(input:checked) to draw the selected ring
and :has(input:focus-visible) for the keyboard focus outline, so the
visual state is driven entirely by CSS — no longer fights focus changes.
The Okta SVG at img.clerk.com/static/okta.svg is monochromatic, so rendering it via background-image leaves it invisible against the dark foreground that ships when the appearance prop selects a dark theme. Switch monochromatic provider icons to mask-image + backgroundColor: $colorForeground so the icon picks up the theme's foreground color and inverts automatically. SAML stays on background-image — its SVG ships in full color and renders correctly on both light and dark backgrounds. Mirrors the existing pattern in common/ProviderIcon.tsx.
|
@alexcarpenter fixed both: |
…ring Both the keyboard focus state and the selected state on the provider card now reuse `common.focusRingStyles` instead of bespoke outline / boxShadow rules. Same helper SimpleButton draws its own focus ring with, so the visual treatment matches the rest of @clerk/ui without re-deriving it here. Also drops the redundant `color: $colorForeground` overrides on the body Text components — Text defaults already render in the foreground color, with `colorScheme='secondary'` swapping in for the muted variant.
Match SimpleButton's outline variant when focused with hoverAsFocus: in addition to the focus ring, the card's own border darkens from $borderAlpha150 to $borderAlpha300 while the inner input has :focus-visible. The ring stays via common.focusRingStyles. Also restores the explicit variant='subtitle' on the body title Text so the visual hierarchy between sub-header and description holds.

Summary
Implements the first wizard step of
<__experimental_ConfigureSSO />— the provider selection screen — and the state machine foundation that makes it work end-to-end. The user picks one of two SAML providers (Okta Workforce, Custom SAML Provider), Continue creates the enterprise connection, and the wizard advances. On reload,deriveInitialSteplands the user on the correct step based on the connection's state. All user-visible copy is wired through@clerk/localizationswith translations for every supported locale. No public component API change.Linear: ORGS-1462
Why
After the layered architecture landed in #8493,
SelectProviderStepwas registered as a regular<Wizard.Step>with a placeholder body. The step is structurally a wizard step (not a pre-wizard gate), but is filtered out of the breadcrumb inConfigureSSOHeaderby id so the visible step count stays at 4 (Verify domain → Configure → Test → Confirmation). This PR fills in the body with the real provider tiles, selection behavior, the localization plumbing — and the flow-context plumbing the rest of the wizard depends on. ThecreateConnectioncall lands here as an interim location; a small follow-up will move it into Verify Domain'sEnterVerificationCodeStep.onResolveonce Laura's #8520 merges.What changed
Select Provider step UI
steps/SelectProviderStep.tsx— replaces the placeholder body with:Select your identity provider+ helper copy)SAMLgroup containing two equal-width tiles laid out viaGrid columns={2}<Alert variant='warning'>) about provider lock-inuseState<ProviderType | null>selection stateuseCardStateStep.Footer.Continuegated onisDisabled={isLastStep || !selected || card.isLoading}; shows a loading state during the async create callStep.Footer.Previousleft as-is (auto-disabled byisFirstStep)localizationKeys('configureSSO.selectProviderStep.*')(no inline literals)ProviderCard(private to the file) —<SimpleButton variant='outline'>with a column-flex icon + label, height$32, gap$2, padding$1x5. Selected state renders a 4pxboxShadowring usingtheme.colors.$colorRing.aria-pressedmirrors the selected state for assistive tech.img.clerk.comstatic CDN viaiconImageUrl('okta')andiconImageUrl('saml'). Rendered as an inline<Span aria-hidden>withbackgroundImage, mirroringProviderIcon's non-mask-image branch — we don't wrap with<ProviderIcon>directly because itsidprop union doesn't include'saml_custom'.elements/Step.tsx— minorStep.Headerpolish: top-align the inner row (align='start') and bump the title/description column gap to$2to match the Figma. No behavior change.State machine foundation
ConfigureSSOContext.tsx— extends the flow context withprovider,setProvider,clearProvider, andcreateConnection.providerderives fromenterpriseConnection?.provider ?? localProvider.createConnectionis wrapped inuseReverification, idempotent (no-ops when a connection already exists), and assembles the payload from the user's primary email domain + active organization id.deriveInitialStep.ts(new) — pure helper that maps a connection state to the wizard step the user should land on: no connection →select-provider, nosamlConnection.idpSsoUrl→configure, otherwise →confirmation. Test step derivation is deferred (no synchronous "last test passed" signal).ConfigureSSO.tsx— wiresWizard.initialStepId={deriveInitialStep(enterpriseConnection)}so reloads land on the right step.SelectProviderStepContinue handler nowsetProvider(selected) → createConnection() → goNext(), all wrapped inuseCardState(setLoading/setIdle/setError) and routed throughhandleErroron rejection.ProviderTyperenamed from UI-side ('okta' | 'custom_saml') to backend values ('saml_okta' | 'saml_custom') so the flow context, the resource call, and the resource's ownproviderfield all agree.Localization
@clerk/shared— adds the typedselectProviderStepnamespace to__internal_LocalizationResource(under__experimental_configureSSO).@clerk/localizations— adds English values inen-US.tsand translations for every other supported locale (~49 files).Out of scope — planned follow-ups
createConnectioninto Verify Domain. Once chore(ui,shared,localizations): Add verify/add email address step to<ConfigureSSO />#8520 merges, the create call moves toEnterVerificationCodeStep.onResolveso the connection is created after email + OTP verification, not on Select Provider Continue. ThecreateConnectionidempotency guard in this PR is what enables that move safely.Test plan
<__experimental_ConfigureSSO />and lands on Select Provider on cold start (deriveInitialStepreturnsselect-provider)img.clerk.comaria-pressedflips on the selected tile (verified via DevTools accessibility tree)setProvider+createConnection+goNextinvoked in order, loading state, error pathderiveInitialSteptable-driven tests cover undefined connection / nosamlConnection/ noidpSsoUrl/ hasidpSsoUrlType of change
__experimental_*surface — no public API change)