Skip to content

feat(ui): Expose profile sub components#8654

Draft
alexcarpenter wants to merge 25 commits into
mainfrom
carp/profile-section-components
Draft

feat(ui): Expose profile sub components#8654
alexcarpenter wants to merge 25 commits into
mainfrom
carp/profile-section-components

Conversation

@alexcarpenter
Copy link
Copy Markdown
Member

@alexcarpenter alexcarpenter commented May 26, 2026

Summary

Exposes UserProfile and OrganizationProfile as composable sub-components from @clerk/ui/experimental. Lets consumers render individual profile sections (Account, Security, Members, Billing, etc.) outside the full modal/page flow.

Approach

  • New composed/ directory — each profile gets a Provider that wires up the required context tree (appearance, environment, module manager, routing, flow metadata) so individual section components render standalone.
  • moduleManagerStore — module-level get/set because composed components mount outside the normal component tree and can't inherit ModuleManager via context from ClerkUI.init().
  • stubRouter — minimal RouteContext implementation delegating to clerk.navigate. Child components call useRouter() internally but composed pages don't do real routing.
  • StyleCacheProvider — moved document.querySelector from module scope into the component body; import-time access breaks SSR.
  • useSafeState — reset isMountedRef to true in effect body; StrictMode cleanup between double-invocation left it permanently false.
  • Animated — guard against StrictMode double-mount leaving animation refs stale.
  • Exported via @clerk/ui/experimental with 'use client' directive.

API

import { UserProfile, OrganizationProfile } from '@clerk/ui/experimental';

<UserProfile>
  <UserProfile.Account />
  <UserProfile.Security />
</UserProfile>

<OrganizationProfile>
  <OrganizationProfile.General />
  <OrganizationProfile.Members />
</OrganizationProfile>

Sub-components available: Account, Security, Billing, APIKeys (user); General, Members, Billing, APIKeys, ConfigureSSO (org). Fine-grained wrappers also exported (e.g. AccountProfile, SecurityPasskeys).

Test plan

  • Composed provider wiring tests verify context parity with full-flow mounts
  • Section-level render tests for both UserProfile and OrganizationProfile
  • StrictMode animation + state tests
  • Stub router limitation tests

🤖 Generated with Claude Code

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 26, 2026

⚠️ No Changeset found

Latest commit: d961ccf

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
Copy link
Copy Markdown

vercel Bot commented May 26, 2026

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

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment May 29, 2026 10:51pm

Request Review

@alexcarpenter
Copy link
Copy Markdown
Member Author

!snapshot

@github-actions

This comment has been minimized.

@alexcarpenter
Copy link
Copy Markdown
Member Author

!snapshot

@github-actions

This comment has been minimized.

@alexcarpenter
Copy link
Copy Markdown
Member Author

!snapshot

@github-actions

This comment has been minimized.

@alexcarpenter
Copy link
Copy Markdown
Member Author

!snapshot

@github-actions

This comment has been minimized.

@alexcarpenter
Copy link
Copy Markdown
Member Author

!snapshot

@github-actions
Copy link
Copy Markdown
Contributor

Hey @alexcarpenter - the snapshot version command generated the following package versions:

Package Version
@clerk/astro 3.3.0-snapshot.v20260527161602
@clerk/backend 3.4.12-snapshot.v20260527161602
@clerk/chrome-extension 3.1.29-snapshot.v20260527161602
@clerk/clerk-js 6.12.0-snapshot.v20260527161602
@clerk/dev-cli 0.1.1-snapshot.v20260527161602
@clerk/expo 3.2.15-snapshot.v20260527161602
@clerk/expo-passkeys 1.0.28-snapshot.v20260527161602
@clerk/express 2.1.20-snapshot.v20260527161602
@clerk/fastify 3.1.30-snapshot.v20260527161602
@clerk/hono 0.1.30-snapshot.v20260527161602
@clerk/localizations 4.6.7-snapshot.v20260527161602
@clerk/msw 0.0.28-snapshot.v20260527161602
@clerk/nextjs 7.4.0-snapshot.v20260527161602
@clerk/nuxt 2.5.0-snapshot.v20260527161602
@clerk/react 6.7.0-snapshot.v20260527161602
@clerk/react-router 3.3.0-snapshot.v20260527161602
@clerk/shared 4.13.0-snapshot.v20260527161602
@clerk/tanstack-react-start 1.3.0-snapshot.v20260527161602
@clerk/testing 2.0.32-snapshot.v20260527161602
@clerk/ui 1.13.0-snapshot.v20260527161602
@clerk/upgrade 2.0.3-snapshot.v20260527161602
@clerk/vue 2.3.0-snapshot.v20260527161602

Tip: Use the snippet copy button below to quickly install the required packages.
@clerk/astro

npm i @clerk/astro@3.3.0-snapshot.v20260527161602 --save-exact

@clerk/backend

npm i @clerk/backend@3.4.12-snapshot.v20260527161602 --save-exact

@clerk/chrome-extension

npm i @clerk/chrome-extension@3.1.29-snapshot.v20260527161602 --save-exact

@clerk/clerk-js

npm i @clerk/clerk-js@6.12.0-snapshot.v20260527161602 --save-exact

@clerk/dev-cli

npm i @clerk/dev-cli@0.1.1-snapshot.v20260527161602 --save-exact

@clerk/expo

npm i @clerk/expo@3.2.15-snapshot.v20260527161602 --save-exact

@clerk/expo-passkeys

npm i @clerk/expo-passkeys@1.0.28-snapshot.v20260527161602 --save-exact

@clerk/express

npm i @clerk/express@2.1.20-snapshot.v20260527161602 --save-exact

@clerk/fastify

npm i @clerk/fastify@3.1.30-snapshot.v20260527161602 --save-exact

@clerk/hono

npm i @clerk/hono@0.1.30-snapshot.v20260527161602 --save-exact

@clerk/localizations

npm i @clerk/localizations@4.6.7-snapshot.v20260527161602 --save-exact

@clerk/msw

npm i @clerk/msw@0.0.28-snapshot.v20260527161602 --save-exact

@clerk/nextjs

npm i @clerk/nextjs@7.4.0-snapshot.v20260527161602 --save-exact

@clerk/nuxt

npm i @clerk/nuxt@2.5.0-snapshot.v20260527161602 --save-exact

@clerk/react

npm i @clerk/react@6.7.0-snapshot.v20260527161602 --save-exact

@clerk/react-router

npm i @clerk/react-router@3.3.0-snapshot.v20260527161602 --save-exact

@clerk/shared

npm i @clerk/shared@4.13.0-snapshot.v20260527161602 --save-exact

@clerk/tanstack-react-start

npm i @clerk/tanstack-react-start@1.3.0-snapshot.v20260527161602 --save-exact

@clerk/testing

npm i @clerk/testing@2.0.32-snapshot.v20260527161602 --save-exact

@clerk/ui

npm i @clerk/ui@1.13.0-snapshot.v20260527161602 --save-exact

@clerk/upgrade

npm i @clerk/upgrade@2.0.3-snapshot.v20260527161602 --save-exact

@clerk/vue

npm i @clerk/vue@2.3.0-snapshot.v20260527161602 --save-exact

alexcarpenter and others added 22 commits May 29, 2026 12:55
Add 'use client' to the experimental entrypoint and move the
document.querySelector call in StyleCacheProvider from module scope
into the useMemo to avoid crashes during server-side rendering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Annotate every exported composed component with a ReactNode return
type so the generated .d.ts files are compatible with both React 18
and React 19 consumers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Export UserProfile and OrganizationProfile as function components
with static properties (via Object.assign) instead of plain objects.
This matches the existing UserButton pattern and is compatible with
React Server Components client references, which support property
access on function exports but not on plain object exports.

The provider is now the root component itself — consumers write
<UserProfile> instead of <UserProfile.Provider>.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The spy returned undefined in jsdom, causing autoAnimate's
MutationObserver callback to crash on .addEventListener.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant