Skip to content

fix(ui): self-serve SSO follow-ups (a11y + UX)#8940

Draft
iagodahlem wants to merge 8 commits into
mainfrom
iago/configuresso-wizard-followups
Draft

fix(ui): self-serve SSO follow-ups (a11y + UX)#8940
iagodahlem wants to merge 8 commits into
mainfrom
iago/configuresso-wizard-followups

Conversation

@iagodahlem

@iagodahlem iagodahlem commented Jun 19, 2026

Copy link
Copy Markdown
Member

Linear: ORGS-1666

Description

Follow-up polish to the self-serve SSO change-provider flow (#8881). On this branch:

  • Accessible provider cards — restore native radio semantics to the provider-selection cards. They had become <button role="radio">, which loses the native radiogroup keyboard contract (arrow-key navigation, roving focus). This returns to a visually-hidden native radio inside the label, keeping the radio dot hidden per design while keyboard a11y works.
  • Resilient change-provider dialog — on a failed change the dialog now stays open with the error shown inline (retry in place), is named for assistive tech via aria-labelledby, and restores Escape-to-close.
  • Stepper completion — wizard steps read as done based on whether their work is complete, not the current position, so re-entering with an active connection shows all steps checked wherever you are.
  • Security page loading — show an overview-shaped loading state instead of the wizard skeleton (it was flashing wizard → overview and dropping the page header).
  • Doc — document the intentional non-atomic delete-then-create window in changeProvider.

Changeset added at wrap-up.

Type of change

  • 🐛 Bug fix

Changing an SSO provider deletes the existing enterprise connection before
creating the new one. Document that this is intentionally non-atomic for the
MVP: a failed create briefly leaves the org without a connection, and recovery
is by design since the next render revalidates the deleted connection away so a
retry becomes a plain create.
…ssible

A failed provider change now surfaces the error inline inside the dialog via the
shared card state, keeping the dialog open so the user can retry or cancel
instead of dropping the error behind a dismissed modal. The dialog also gains an
accessible name (aria-labelledby wired to its heading) and restores
Escape-to-close (ignored while a change is in progress). Threads
aria-labelledby/aria-label and onKeyDown through the Modal primitive onto the
role=dialog node.
Replace the role=radio buttons with the established radio-card pattern: a
visually hidden native radio inside a label, with the selected and focus styling
driven by :has(input:checked) and :has(input:focus-visible). This restores
native radiogroup keyboard semantics (arrow-key navigation and roving tabindex)
that role=radio on a button drops, while keeping the visible radio dot removed
per the design. The radio stays in the accessibility tree (sr-only, not
display:none) and names itself from the wrapping label.

Also wires the change-provider dialog to own its submit/error state so the step
re-throws on failure, and adds coverage for the inline error, Escape-to-close,
and the dialog's accessible name.
@changeset-bot

changeset-bot Bot commented Jun 19, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 821c1e7

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel

vercel Bot commented Jun 19, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Jun 19, 2026 8:42pm
swingset Ready Ready Preview, Comment Jun 19, 2026 8:42pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: ca9bcd41-81ca-4793-aa82-d64e866974d3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new

pkg-pr-new Bot commented Jun 19, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@8940

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@8940

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@8940

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@8940

@clerk/eslint-plugin

npm i https://pkg.pr.new/@clerk/eslint-plugin@8940

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@8940

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@8940

@clerk/express

npm i https://pkg.pr.new/@clerk/express@8940

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@8940

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@8940

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@8940

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@8940

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@8940

@clerk/react

npm i https://pkg.pr.new/@clerk/react@8940

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@8940

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@8940

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@8940

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@8940

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@8940

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@8940

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@8940

commit: 821c1e7

The SSO wizard stepper derived each step's completed tick positionally
(sits before the current step), so navigating back un-ticked steps whose
work was actually done. Re-entering an already-active connection showed
later steps as incomplete depending on where the user stood.

Add an optional per-step `isComplete` predicate to the wizard step config,
resolved into the stepper's `isCompleted` flag, with the positional value
kept as the fallback so wizards that declare no predicate are unchanged.
The labeled outer steps now report completion from the same connection
flags their guards use, so an active connection shows every step ticked
regardless of the current position.
…ity page

The security page rendered a wizard-shaped skeleton (stepper + centered
spinner + disabled footer) while loading, even though the default view is
the overview card. On load this flashed a wizard layout that then popped
into a different overview card, and the page "Security" header was missing
during load.

While loading in the overview view, keep the page chrome stable — the
ProfileCard.Page and the "Security" header — and render an overview-shaped
placeholder for the SSO section (the section frame with an in-frame
spinner) so the settled overview replaces it in place. The wizard skeleton
now only renders when loading happens within the wizard view.
…inner

Replace the SSO section-framed loading placeholder with a bare spinner
centered in the remaining content height beneath the Security header,
matching the design. Adds an opt-in sx hook to ProfileCardPage so the
overview can fill the scroll box height during load.
Render the Checkmark icon whenever isCompleted, removing the previous
!isCurrent guard. A step that is both current and completed now shows
the checkmark (on the dark "you are here" background) instead of
falling through to its number.

Background color precedence is unchanged: isCurrent takes priority over
isCompleted, so the bullet stays the dark $colorForeground circle —
only the icon inside changes from number to checkmark.

Update the navigation test: for a fully active connection all four
steps are completed, so all four bullets render checkmarks and zero
show a digit (including the current step).
When a step is both current and completed the bullet background is
\$colorForeground (light/white in dark mode). The checkmark was always
colored \$white, making it invisible. Use \$colorBackground (the inverse)
for the current step — the same token the step number already uses —
so the check stays readable in both themes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant