Skip to content

feat(ui): Expose composed profile components - #9144

Merged
alexcarpenter merged 11 commits into
mainfrom
carp/profile-release
Jul 24, 2026
Merged

feat(ui): Expose composed profile components#9144
alexcarpenter merged 11 commits into
mainfrom
carp/profile-release

Conversation

@alexcarpenter

@alexcarpenteralexcarpenter commented Jul 13, 2026

Copy link
Copy Markdown
Member

Ships the experimental composed profile API under @clerk/ui/experimental. Lets developers build the profile UI from flat, individually-mountable panel and section components instead of the monolithic <UserProfile /> / <OrganizationProfile />. Each export is a top-level client reference, so it renders directly in an RSC tree without a consumer 'use client' boundary.

What this exposes

New entrypoint: @clerk/ui/experimental.

UserProfile

  • Provider: UserProfileProvider
  • Panels: UserProfileAccountPanel, UserProfileSecurityPanel, UserProfileBillingPanel, UserProfileAPIKeysPanel
  • Account sections: UserProfileProfileSection, UserProfileUsernameSection, UserProfileEmailSection, UserProfilePhoneSection, UserProfileConnectedAccountsSection, UserProfileEnterpriseAccountsSection, UserProfileWeb3Section
  • Security sections: UserProfilePasswordSection, UserProfilePasskeysSection, UserProfileMfaSection, UserProfileActiveDevicesSection, UserProfileDeleteSection

OrganizationProfile

  • Provider: OrganizationProfileProvider
  • Panels: OrganizationProfileGeneralPanel, OrganizationProfileMembersPanel, OrganizationProfileBillingPanel, OrganizationProfileAPIKeysPanel, OrganizationProfileSecurityPanel
  • Sections: OrganizationProfileProfileSection, OrganizationProfileDomainsSection, OrganizationProfileLeaveSection, OrganizationProfileDeleteSection

Section wrappers render the same underlying components as standard <UserProfile /> / <OrganizationProfile />, so behavior matches; E2E parity coverage added.

Experimental: API may change; gated behind the /experimental entrypoint.

@vercel

vercelBot commented Jul 13, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
clerk-js-sandboxReadyReadyPreview, CommentJul 21, 2026 11:31pm
swingsetReadyReadyPreview, CommentJul 21, 2026 11:31pm

Request Review

@changeset-bot

changeset-botBot commented Jul 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: cd3228b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 23 packages
NameType
@clerk/uiMinor
@clerk/clerk-jsPatch
@clerk/sharedPatch
@clerk/reactPatch
@clerk/astroPatch
@clerk/chrome-extensionPatch
@clerk/swingsetPatch
@clerk/vuePatch
@clerk/electronPatch
@clerk/expoPatch
@clerk/backendPatch
@clerk/expo-passkeysPatch
@clerk/expressPatch
@clerk/fastifyPatch
@clerk/headlessPatch
@clerk/honoPatch
@clerk/localizationsPatch
@clerk/mswPatch
@clerk/nextjsPatch
@clerk/nuxtPatch
@clerk/react-routerPatch
@clerk/tanstack-react-startPatch
@clerk/testingPatch

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

@coderabbitai

coderabbitaiBot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change introduces experimental composable UserProfile and OrganizationProfile exports through @clerk/ui/experimental. It adds providers, panels, sections, routing, runtime module-manager access, shared style-cache handling, profile layout primitives, and conditional rendering logic. It also refactors account and security pages, improves Web3 error handling and animation lifecycle management, and adds unit, Vitest, and Playwright coverage for composed flows and exports.

Estimated code review effort: 5 (Critical) | ~120 minutes

Suggested reviewers:brkalow

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 8.70% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Title check✅ PassedThe title clearly summarizes the main change: exposing composed profile components in the UI package.
Description check✅ PassedThe description matches the changeset by documenting the experimental composed profile API and its exported panels and sections.

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

@pkg-pr-new

pkg-pr-newBot commented Jul 13, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

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

@clerk/backend

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

@clerk/chrome-extension

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

@clerk/clerk-js

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

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@9144

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@9144

@clerk/eslint-plugin

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

@clerk/expo

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

@clerk/expo-google-signin

npm i https://pkg.pr.new/@clerk/expo-google-signin@9144

@clerk/expo-passkeys

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

@clerk/express

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

@clerk/fastify

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

@clerk/hono

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

@clerk/localizations

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

@clerk/nextjs

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

@clerk/nuxt

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

@clerk/react

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

@clerk/react-router

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

@clerk/shared

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

@clerk/tanstack-react-start

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

@clerk/testing

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

@clerk/ui

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

@clerk/upgrade

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

@clerk/vue

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

commit: cd3228b

@github-actions

github-actionsBot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

API Changes Report

Generated by Break Check on 2026-07-21T23:33:34.901Z

Summary

MetricCount
Packages analyzed19
Packages with changes1
🔴 Breaking changes0
🟡 Non-breaking changes1
🟢 Additions1

🤖 This report was reviewed by claude-sonnet-4-6.


@clerk/ui

Current version: 1.25.6
Recommended bump: MINOR → 1.26.0

Subpath ./experimental

🟢 Additions (1)

Added: ./experimental

New subpath export ./experimental (27 exported members)

Subpath ./internal

🟡 Non-breaking Changes (1)

Modified: ElementsConfig
// ... 391 unchanged lines elided ...
profileSectionPrimaryButton: WithOptions<ProfileSectionId>;
profileSectionButtonGroup: WithOptions<ProfileSectionId>;
profilePage: WithOptions<ProfilePageId>;
+ profilePageContent: WithOptions;
formattedPhoneNumber: WithOptions;
formattedPhoneNumberFlag: WithOptions;
formattedPhoneNumberText: WithOptions;
// ... 158 unchanged lines elided ...

Static analyzer: Breaking change in type alias ElementsConfig: Type changed: {button:import("@clerk/ui").~WithOptions<string>;input:import("@clerk/ui").~WithOptions;checkbox:import("@clerk/ui").~W…{button:import("@clerk/ui").~WithOptions<string>;input:import("@clerk/ui").~WithOptions;checkbox:import("@clerk/ui").~W…

🤖 AI review (reclassified as non-breaking) (85%): The elided section grew by exactly one line (475 → 476), indicating a new key was added to ElementsConfig; ElementsConfig is used only as a mapped-type source for the output type Elements, so consumers never construct values of this type directly — adding a new output-only property is non-breaking.


Report generated by Break Check

Last ran on cd3228b.

@alexcarpenter

Copy link
Copy Markdown
MemberAuthor

!snapshot

@github-actions

Copy link
Copy Markdown
Contributor

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

PackageVersion
@clerk/astro3.4.19-snapshot.v20260716135136
@clerk/backend3.11.7-snapshot.v20260716135136
@clerk/chrome-extension3.1.54-snapshot.v20260716135136
@clerk/clerk-js6.25.5-snapshot.v20260716135136
@clerk/electron0.0.15-snapshot.v20260716135136
@clerk/electron-passkeys0.0.4-snapshot.v20260716135136
@clerk/eslint-plugin0.2.1-snapshot.v20260716135136
@clerk/expo3.7.7-snapshot.v20260716135136
@clerk/expo-passkeys1.2.6-snapshot.v20260716135136
@clerk/express2.1.43-snapshot.v20260716135136
@clerk/fastify3.1.53-snapshot.v20260716135136
@clerk/headless0.0.13-snapshot.v20260716135136
@clerk/hono0.1.53-snapshot.v20260716135136
@clerk/localizations4.13.5-snapshot.v20260716135136
@clerk/msw0.0.49-snapshot.v20260716135136
@clerk/nextjs7.5.20-snapshot.v20260716135136
@clerk/nuxt2.6.19-snapshot.v20260716135136
@clerk/react6.12.5-snapshot.v20260716135136
@clerk/react-router3.5.12-snapshot.v20260716135136
@clerk/shared4.25.5-snapshot.v20260716135136
@clerk/swingset0.0.20-snapshot.v20260716135136
@clerk/tanstack-react-start1.4.20-snapshot.v20260716135136
@clerk/testing2.2.10-snapshot.v20260716135136
@clerk/ui1.26.0-snapshot.v20260716135136
@clerk/upgrade2.0.5-snapshot.v20260716135136
@clerk/vue2.4.17-snapshot.v20260716135136

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

npm i @clerk/astro@3.4.19-snapshot.v20260716135136 --save-exact

@clerk/backend

npm i @clerk/backend@3.11.7-snapshot.v20260716135136 --save-exact

@clerk/chrome-extension

npm i @clerk/chrome-extension@3.1.54-snapshot.v20260716135136 --save-exact

@clerk/clerk-js

npm i @clerk/clerk-js@6.25.5-snapshot.v20260716135136 --save-exact

@clerk/electron

npm i @clerk/electron@0.0.15-snapshot.v20260716135136 --save-exact

@clerk/electron-passkeys

npm i @clerk/electron-passkeys@0.0.4-snapshot.v20260716135136 --save-exact

@clerk/eslint-plugin

npm i @clerk/eslint-plugin@0.2.1-snapshot.v20260716135136 --save-exact

@clerk/expo

npm i @clerk/expo@3.7.7-snapshot.v20260716135136 --save-exact

@clerk/expo-passkeys

npm i @clerk/expo-passkeys@1.2.6-snapshot.v20260716135136 --save-exact

@clerk/express

npm i @clerk/express@2.1.43-snapshot.v20260716135136 --save-exact

@clerk/fastify

npm i @clerk/fastify@3.1.53-snapshot.v20260716135136 --save-exact

@clerk/headless

npm i @clerk/headless@0.0.13-snapshot.v20260716135136 --save-exact

@clerk/hono

npm i @clerk/hono@0.1.53-snapshot.v20260716135136 --save-exact

@clerk/localizations

npm i @clerk/localizations@4.13.5-snapshot.v20260716135136 --save-exact

@clerk/msw

npm i @clerk/msw@0.0.49-snapshot.v20260716135136 --save-exact

@clerk/nextjs

npm i @clerk/nextjs@7.5.20-snapshot.v20260716135136 --save-exact

@clerk/nuxt

npm i @clerk/nuxt@2.6.19-snapshot.v20260716135136 --save-exact

@clerk/react

npm i @clerk/react@6.12.5-snapshot.v20260716135136 --save-exact

@clerk/react-router

npm i @clerk/react-router@3.5.12-snapshot.v20260716135136 --save-exact

@clerk/shared

npm i @clerk/shared@4.25.5-snapshot.v20260716135136 --save-exact

@clerk/swingset

npm i @clerk/swingset@0.0.20-snapshot.v20260716135136 --save-exact

@clerk/tanstack-react-start

npm i @clerk/tanstack-react-start@1.4.20-snapshot.v20260716135136 --save-exact

@clerk/testing

npm i @clerk/testing@2.2.10-snapshot.v20260716135136 --save-exact

@clerk/ui

npm i @clerk/ui@1.26.0-snapshot.v20260716135136 --save-exact

@clerk/upgrade

npm i @clerk/upgrade@2.0.5-snapshot.v20260716135136 --save-exact

@clerk/vue

npm i @clerk/vue@2.4.17-snapshot.v20260716135136 --save-exact

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (5)
packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx (1)

31-55: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Memoize the context value to avoid needless consumer re-renders.

orgProfileCtxValue (including a brand-new customPages: [] array) is recreated on every render and passed straight into OrganizationProfileContext.Provider. Any consumer relying on referential identity (e.g. a useEffect/useMemo dependency on customPages or the context object itself) will re-run needlessly on every re-render of this provider.

♻️ Suggested fix
- const orgProfileCtxValue = {- componentName: 'OrganizationProfile' as const,- mode: 'mounted' as const,- routing: 'hash' as const,- path: undefined,- afterLeaveOrganizationUrl,- apiKeysProps,- customPages: [],- };+ const orgProfileCtxValue = useMemo(+ () => ({+ componentName: 'OrganizationProfile' as const,+ mode: 'mounted' as const,+ routing: 'hash' as const,+ path: undefined,+ afterLeaveOrganizationUrl,+ apiKeysProps,+ customPages: [],+ }),+ [afterLeaveOrganizationUrl, apiKeysProps],+ );

As per coding guidelines, **/*.{tsx,jsx} should "Minimize re-renders in React components" and "Use proper useMemo for expensive computations in React components."

🤖 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/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx`
around lines 31 - 55, Memoize orgProfileCtxValue in OrganizationProfileProvider
so its object identity remains stable across renders, including the customPages
array. Use React’s memoization hook with dependencies covering
afterLeaveOrganizationUrl and apiKeysProps, while keeping the existing context
fields and provider behavior unchanged.

Source: Coding guidelines

packages/ui/src/experimental/index.ts (1)

10-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace the chained wildcard barrels with deliberate public exports.

The intermediate and published barrels together expose future symbols and collisions through @clerk/ui/experimental.

  • packages/ui/src/experimental/index.ts#L10-L10: explicitly export the supported experimental components from their leaf modules.
  • packages/ui/src/composed/index.ts#L1-L2: remove the intermediate wildcard aggregation or replace it with an explicit internal export list.

As per coding guidelines, “Avoid barrel files (index.ts re-exports) as they can cause circular dependencies.”

🤖 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/ui/src/experimental/index.ts` at line 10, Replace the wildcard
export in packages/ui/src/experimental/index.ts at line 10 with explicit exports
of the supported experimental components from their leaf modules. In
packages/ui/src/composed/index.ts at lines 1-2, remove the wildcard aggregation
or replace it with an explicit internal export list so future symbols and
collisions are not exposed.

Source: Coding guidelines

integration/tests/composed-components.test.ts (1)

31-45: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add an integration fixture without a local 'use client' boundary.

This page becomes a Client Component, so it cannot verify the advertised ability to import and render these exports directly from a React Server Component. Add a minimal server page that imports the experimental components and asserts they render.

As per coding guidelines, include tests for all new features.

🤖 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 `@integration/tests/composed-components.test.ts` around lines 31 - 45, Update
the composedUserProfilePage fixture to remove the local 'use client' directive
and keep it as a minimal React Server Component that imports and renders the
experimental UserProfile exports. Ensure the integration test asserts successful
rendering from this server page, covering the direct server-component import
path for all newly supported components.

Source: Coding guidelines

packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx (1)

18-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add explicit return types to exported components.

  • packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx#L18-L18: annotate the component return type.
  • packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx#L46-L46: annotate the newly exported component return type.
  • packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx#L26-L26: annotate the exported component return type.

As per coding guidelines, exported TypeScript APIs require explicit return types; based on learnings, this repository enforces that for exported functions.

🤖 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/ui/src/elements/ProfileCard/ProfilePagePanel.tsx` at line 18, Add
explicit return type annotations to the exported components ProfilePagePanel,
ConfigureSSO, and ProfileCardPage. Update each component declaration at
packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx:18-18,
packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx:46-46, and
packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx:26-26, using the
appropriate React component return type while preserving their existing
behavior.

Sources: Coding guidelines, Learnings

packages/ui/src/composed/UserProfile/UserProfileProvider.tsx (1)

29-37: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Memoize the context value to avoid re-rendering the whole composed subtree.

userProfileCtxValue is a new object every render, so all descendants consuming UserProfileContext re-render on every UserProfileProvider render regardless of whether any field changed. ProfileProviderShell already memoizes its comparable derived values (router, options), so this is inconsistent with the pattern elsewhere in the layer.

As per coding guidelines, "**/*.{jsx,tsx}": "Use proper useMemo for expensive computations in React components" and "Minimize re-renders in React components."

♻️ Proposed fix
+import { useMemo } from 'react';
...
- const userProfileCtxValue = {- componentName: 'UserProfile' as const,- mode: 'mounted' as const,- routing: 'hash' as const,- path: undefined,- additionalOAuthScopes,- apiKeysProps,- customPages: [],- };+ const userProfileCtxValue = useMemo(+ () => ({+ componentName: 'UserProfile' as const,+ mode: 'mounted' as const,+ routing: 'hash' as const,+ path: undefined,+ additionalOAuthScopes,+ apiKeysProps,+ customPages: [],+ }),+ [additionalOAuthScopes, apiKeysProps],+ );
🤖 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/ui/src/composed/UserProfile/UserProfileProvider.tsx` around lines 29
- 37, Memoize the userProfileCtxValue object in UserProfileProvider with
React.useMemo, using all values included in the context object—especially
additionalOAuthScopes and apiKeysProps—as dependencies; preserve the existing
constant fields and empty customPages value.

Source: Coding guidelines

🤖 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 `@integration/tests/composed-components.test.ts`:
- Around line 127-130: Update the afterAll cleanup blocks around fake users,
organizations, and related temporary entities to use try/finally so each entity
deletion is attempted safely and app.teardown() always runs independently of API
cleanup failures. Preserve the existing cleanup targets and ordering where
possible while ensuring failures in assertions or deletion do not prevent
subsequent cleanup.
In `@packages/ui/src/composed/__tests__/action-animation.test.tsx`:
- Around line 16-26: Replace any-based animation helper types with
Parameters<Element['animate']> call tuples and Keyframe/Keyframe[] types in
findAddAnimationCall and the corresponding helpers in
packages/ui/src/composed/__tests__/action-animation.test.tsx (lines 16-26) and
packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx (lines
28-48). In packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx
(lines 62-68), replace the as any mock result with an Animation-typed fixture or
narrow Partial<Animation> cast.
In `@packages/ui/src/styledSystem/createEmotionCache.ts`:
- Around line 3-4: Update the Emotion insert override in createEmotionCache so
its assigned function inherits cache.insert’s parameter types instead of
declaring an explicit any; keep sheet typed as Emotion’s StyleSheet and remove
the now-unused SerializedStyles import.
---
Nitpick comments:
In `@integration/tests/composed-components.test.ts`:
- Around line 31-45: Update the composedUserProfilePage fixture to remove the
local 'use client' directive and keep it as a minimal React Server Component
that imports and renders the experimental UserProfile exports. Ensure the
integration test asserts successful rendering from this server page, covering
the direct server-component import path for all newly supported components.
In
`@packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx`:
- Around line 31-55: Memoize orgProfileCtxValue in OrganizationProfileProvider
so its object identity remains stable across renders, including the customPages
array. Use React’s memoization hook with dependencies covering
afterLeaveOrganizationUrl and apiKeysProps, while keeping the existing context
fields and provider behavior unchanged.
In `@packages/ui/src/composed/UserProfile/UserProfileProvider.tsx`:
- Around line 29-37: Memoize the userProfileCtxValue object in
UserProfileProvider with React.useMemo, using all values included in the context
object—especially additionalOAuthScopes and apiKeysProps—as dependencies;
preserve the existing constant fields and empty customPages value.
In `@packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx`:
- Line 18: Add explicit return type annotations to the exported components
ProfilePagePanel, ConfigureSSO, and ProfileCardPage. Update each component
declaration at packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx:18-18,
packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx:46-46, and
packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx:26-26, using the
appropriate React component return type while preserving their existing
behavior.
In `@packages/ui/src/experimental/index.ts`:
- Line 10: Replace the wildcard export in packages/ui/src/experimental/index.ts
at line 10 with explicit exports of the supported experimental components from
their leaf modules. In packages/ui/src/composed/index.ts at lines 1-2, remove
the wildcard aggregation or replace it with an explicit internal export list so
future symbols and collisions are not exposed.
🪄 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 Plus

Run ID: 4b6a5164-137f-461f-85b0-6ad847013b23

📥 Commits

Reviewing files that changed from the base of the PR and between 430ae23 and 3464ff9.

⛔ Files ignored due to path filters (1)
  • packages/ui/src/experimental/__tests__/__snapshots__/flat-exports.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (85)
  • .changeset/profile-section-components.md
  • .changeset/shared-moduleManager-registry.md
  • integration/tests/composed-components.test.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/react/src/__tests__/isomorphicClerk.test.ts
  • packages/react/src/isomorphicClerk.ts
  • packages/shared/src/types/clerk.ts
  • packages/ui/package.json
  • packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationBillingPage.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationGeneralPage.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationMembers.tsx
  • packages/ui/src/components/UserProfile/APIKeysPage.tsx
  • packages/ui/src/components/UserProfile/AccountPage.tsx
  • packages/ui/src/components/UserProfile/AccountSections.tsx
  • packages/ui/src/components/UserProfile/BillingPage.tsx
  • packages/ui/src/components/UserProfile/SecurityPage.tsx
  • packages/ui/src/components/UserProfile/SecuritySections.tsx
  • packages/ui/src/components/UserProfile/Web3Form.tsx
  • packages/ui/src/components/UserProfile/__tests__/AccountSections.test.tsx
  • packages/ui/src/components/UserProfile/__tests__/SecuritySections.test.tsx
  • packages/ui/src/components/UserProfile/__tests__/Web3Section.test.tsx
  • packages/ui/src/composed/APIKeysSection.tsx
  • packages/ui/src/composed/BillingSection.tsx
  • packages/ui/src/composed/OrganizationProfile/APIKeys.tsx
  • packages/ui/src/composed/OrganizationProfile/Billing.tsx
  • packages/ui/src/composed/OrganizationProfile/General.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralDeleteOrganization.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralLeaveOrganization.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralOrganizationProfile.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralVerifiedDomains.tsx
  • packages/ui/src/composed/OrganizationProfile/Members.tsx
  • packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx
  • packages/ui/src/composed/OrganizationProfile/Security.tsx
  • packages/ui/src/composed/OrganizationProfile/index.tsx
  • packages/ui/src/composed/PageContext.tsx
  • packages/ui/src/composed/ProfileProviderShell.tsx
  • packages/ui/src/composed/UserProfile/APIKeys.tsx
  • packages/ui/src/composed/UserProfile/Account.tsx
  • packages/ui/src/composed/UserProfile/AccountConnectedAccounts.tsx
  • packages/ui/src/composed/UserProfile/AccountEmails.tsx
  • packages/ui/src/composed/UserProfile/AccountEnterpriseAccounts.tsx
  • packages/ui/src/composed/UserProfile/AccountPhone.tsx
  • packages/ui/src/composed/UserProfile/AccountProfile.tsx
  • packages/ui/src/composed/UserProfile/AccountUsername.tsx
  • packages/ui/src/composed/UserProfile/AccountWeb3.tsx
  • packages/ui/src/composed/UserProfile/Billing.tsx
  • packages/ui/src/composed/UserProfile/Security.tsx
  • packages/ui/src/composed/UserProfile/SecurityActiveDevices.tsx
  • packages/ui/src/composed/UserProfile/SecurityDelete.tsx
  • packages/ui/src/composed/UserProfile/SecurityMfa.tsx
  • packages/ui/src/composed/UserProfile/SecurityPasskeys.tsx
  • packages/ui/src/composed/UserProfile/SecurityPassword.tsx
  • packages/ui/src/composed/UserProfile/UserProfileProvider.tsx
  • packages/ui/src/composed/UserProfile/index.tsx
  • packages/ui/src/composed/__tests__/OrganizationProfile.test.tsx
  • packages/ui/src/composed/__tests__/OrganizationProfileSections.test.tsx
  • packages/ui/src/composed/__tests__/UserProfile.test.tsx
  • packages/ui/src/composed/__tests__/UserProfileSections.test.tsx
  • packages/ui/src/composed/__tests__/action-animation.test.tsx
  • packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx
  • packages/ui/src/composed/__tests__/composed-provider-wiring.test.tsx
  • packages/ui/src/composed/__tests__/hotload-vs-bundle-risks.test.tsx
  • packages/ui/src/composed/__tests__/stub-limitations.test.ts
  • packages/ui/src/composed/__tests__/style-cache-sharing.test.tsx
  • packages/ui/src/composed/createSection.tsx
  • packages/ui/src/composed/index.ts
  • packages/ui/src/composed/stubRouter.ts
  • packages/ui/src/composed/useBillingRouter.ts
  • packages/ui/src/composed/useRequirePage.ts
  • packages/ui/src/customizables/elementDescriptors.ts
  • packages/ui/src/elements/Animated.tsx
  • packages/ui/src/elements/AppearanceOverrides.tsx
  • packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx
  • packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx
  • packages/ui/src/elements/ProfileCard/__tests__/ProfilePagePanel.test.tsx
  • packages/ui/src/elements/ProfileCard/index.ts
  • packages/ui/src/experimental/__tests__/flat-exports.test.ts
  • packages/ui/src/experimental/index.ts
  • packages/ui/src/hooks/useSafeState.ts
  • packages/ui/src/internal/appearance.ts
  • packages/ui/src/internal/styleCacheStore.ts
  • packages/ui/src/styledSystem/StyleCacheProvider.tsx
  • packages/ui/src/styledSystem/createEmotionCache.ts
  • packages/ui/tsdown.config.mts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • clerk/clerk_go(manual)
  • clerk/dashboard(manual)
  • clerk/accounts(manual)
  • clerk/backoffice(manual)
  • clerk/clerk(manual)
  • clerk/clerk-docs(manual)
  • clerk/cloudflare-workers(manual)

Comment threadintegration/tests/composed-components.test.ts
Comment threadpackages/ui/src/composed/__tests__/action-animation.test.tsx Outdated
Comment threadpackages/ui/src/styledSystem/createEmotionCache.ts Outdated
- Remove `any` from createEmotionCache insert override and animation test helpers
- Type animation call tuples via Parameters<Element['animate']>
- Make integration test cleanup failure-safe with try/finally
@alexcarpenteralexcarpenter changed the title feat(ui): composed profile components (release)feat(ui): Expose composed profile componentsJul 22, 2026
@alexcarpenter
alexcarpenter merged commit 01f2c12 into mainJul 24, 2026
55 checks passed
@alexcarpenter
alexcarpenter deleted the carp/profile-release branch July 24, 2026 13:30
Sign up for freeto 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.

2 participants

@alexcarpenter@brkalow
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
feat(ui): Expose composed profile components by alexcarpenter · Pull Request #9144 · clerk/javascript · GitHub
Skip to content

feat(ui): Expose composed profile components - #9144

Merged
alexcarpenter merged 11 commits into
mainfrom
carp/profile-release
Jul 24, 2026
Merged

feat(ui): Expose composed profile components#9144
alexcarpenter merged 11 commits into
mainfrom
carp/profile-release

Conversation

@alexcarpenter

@alexcarpenteralexcarpenter commented Jul 13, 2026

Copy link
Copy Markdown
Member

Ships the experimental composed profile API under @clerk/ui/experimental. Lets developers build the profile UI from flat, individually-mountable panel and section components instead of the monolithic <UserProfile /> / <OrganizationProfile />. Each export is a top-level client reference, so it renders directly in an RSC tree without a consumer 'use client' boundary.

What this exposes

New entrypoint: @clerk/ui/experimental.

UserProfile

  • Provider: UserProfileProvider
  • Panels: UserProfileAccountPanel, UserProfileSecurityPanel, UserProfileBillingPanel, UserProfileAPIKeysPanel
  • Account sections: UserProfileProfileSection, UserProfileUsernameSection, UserProfileEmailSection, UserProfilePhoneSection, UserProfileConnectedAccountsSection, UserProfileEnterpriseAccountsSection, UserProfileWeb3Section
  • Security sections: UserProfilePasswordSection, UserProfilePasskeysSection, UserProfileMfaSection, UserProfileActiveDevicesSection, UserProfileDeleteSection

OrganizationProfile

  • Provider: OrganizationProfileProvider
  • Panels: OrganizationProfileGeneralPanel, OrganizationProfileMembersPanel, OrganizationProfileBillingPanel, OrganizationProfileAPIKeysPanel, OrganizationProfileSecurityPanel
  • Sections: OrganizationProfileProfileSection, OrganizationProfileDomainsSection, OrganizationProfileLeaveSection, OrganizationProfileDeleteSection

Section wrappers render the same underlying components as standard <UserProfile /> / <OrganizationProfile />, so behavior matches; E2E parity coverage added.

Experimental: API may change; gated behind the /experimental entrypoint.

@vercel

vercelBot commented Jul 13, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
clerk-js-sandboxReadyReadyPreview, CommentJul 21, 2026 11:31pm
swingsetReadyReadyPreview, CommentJul 21, 2026 11:31pm

Request Review

@changeset-bot

changeset-botBot commented Jul 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: cd3228b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 23 packages
NameType
@clerk/uiMinor
@clerk/clerk-jsPatch
@clerk/sharedPatch
@clerk/reactPatch
@clerk/astroPatch
@clerk/chrome-extensionPatch
@clerk/swingsetPatch
@clerk/vuePatch
@clerk/electronPatch
@clerk/expoPatch
@clerk/backendPatch
@clerk/expo-passkeysPatch
@clerk/expressPatch
@clerk/fastifyPatch
@clerk/headlessPatch
@clerk/honoPatch
@clerk/localizationsPatch
@clerk/mswPatch
@clerk/nextjsPatch
@clerk/nuxtPatch
@clerk/react-routerPatch
@clerk/tanstack-react-startPatch
@clerk/testingPatch

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

@coderabbitai

coderabbitaiBot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change introduces experimental composable UserProfile and OrganizationProfile exports through @clerk/ui/experimental. It adds providers, panels, sections, routing, runtime module-manager access, shared style-cache handling, profile layout primitives, and conditional rendering logic. It also refactors account and security pages, improves Web3 error handling and animation lifecycle management, and adds unit, Vitest, and Playwright coverage for composed flows and exports.

Estimated code review effort: 5 (Critical) | ~120 minutes

Suggested reviewers:brkalow

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 8.70% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Title check✅ PassedThe title clearly summarizes the main change: exposing composed profile components in the UI package.
Description check✅ PassedThe description matches the changeset by documenting the experimental composed profile API and its exported panels and sections.

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

@pkg-pr-new

pkg-pr-newBot commented Jul 13, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

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

@clerk/backend

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

@clerk/chrome-extension

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

@clerk/clerk-js

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

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@9144

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@9144

@clerk/eslint-plugin

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

@clerk/expo

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

@clerk/expo-google-signin

npm i https://pkg.pr.new/@clerk/expo-google-signin@9144

@clerk/expo-passkeys

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

@clerk/express

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

@clerk/fastify

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

@clerk/hono

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

@clerk/localizations

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

@clerk/nextjs

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

@clerk/nuxt

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

@clerk/react

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

@clerk/react-router

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

@clerk/shared

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

@clerk/tanstack-react-start

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

@clerk/testing

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

@clerk/ui

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

@clerk/upgrade

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

@clerk/vue

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

commit: cd3228b

@github-actions

github-actionsBot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

API Changes Report

Generated by Break Check on 2026-07-21T23:33:34.901Z

Summary

MetricCount
Packages analyzed19
Packages with changes1
🔴 Breaking changes0
🟡 Non-breaking changes1
🟢 Additions1

🤖 This report was reviewed by claude-sonnet-4-6.


@clerk/ui

Current version: 1.25.6
Recommended bump: MINOR → 1.26.0

Subpath ./experimental

🟢 Additions (1)

Added: ./experimental

New subpath export ./experimental (27 exported members)

Subpath ./internal

🟡 Non-breaking Changes (1)

Modified: ElementsConfig
// ... 391 unchanged lines elided ...
profileSectionPrimaryButton: WithOptions<ProfileSectionId>;
profileSectionButtonGroup: WithOptions<ProfileSectionId>;
profilePage: WithOptions<ProfilePageId>;
+ profilePageContent: WithOptions;
formattedPhoneNumber: WithOptions;
formattedPhoneNumberFlag: WithOptions;
formattedPhoneNumberText: WithOptions;
// ... 158 unchanged lines elided ...

Static analyzer: Breaking change in type alias ElementsConfig: Type changed: {button:import("@clerk/ui").~WithOptions<string>;input:import("@clerk/ui").~WithOptions;checkbox:import("@clerk/ui").~W…{button:import("@clerk/ui").~WithOptions<string>;input:import("@clerk/ui").~WithOptions;checkbox:import("@clerk/ui").~W…

🤖 AI review (reclassified as non-breaking) (85%): The elided section grew by exactly one line (475 → 476), indicating a new key was added to ElementsConfig; ElementsConfig is used only as a mapped-type source for the output type Elements, so consumers never construct values of this type directly — adding a new output-only property is non-breaking.


Report generated by Break Check

Last ran on cd3228b.

@alexcarpenter

Copy link
Copy Markdown
MemberAuthor

!snapshot

@github-actions

Copy link
Copy Markdown
Contributor

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

PackageVersion
@clerk/astro3.4.19-snapshot.v20260716135136
@clerk/backend3.11.7-snapshot.v20260716135136
@clerk/chrome-extension3.1.54-snapshot.v20260716135136
@clerk/clerk-js6.25.5-snapshot.v20260716135136
@clerk/electron0.0.15-snapshot.v20260716135136
@clerk/electron-passkeys0.0.4-snapshot.v20260716135136
@clerk/eslint-plugin0.2.1-snapshot.v20260716135136
@clerk/expo3.7.7-snapshot.v20260716135136
@clerk/expo-passkeys1.2.6-snapshot.v20260716135136
@clerk/express2.1.43-snapshot.v20260716135136
@clerk/fastify3.1.53-snapshot.v20260716135136
@clerk/headless0.0.13-snapshot.v20260716135136
@clerk/hono0.1.53-snapshot.v20260716135136
@clerk/localizations4.13.5-snapshot.v20260716135136
@clerk/msw0.0.49-snapshot.v20260716135136
@clerk/nextjs7.5.20-snapshot.v20260716135136
@clerk/nuxt2.6.19-snapshot.v20260716135136
@clerk/react6.12.5-snapshot.v20260716135136
@clerk/react-router3.5.12-snapshot.v20260716135136
@clerk/shared4.25.5-snapshot.v20260716135136
@clerk/swingset0.0.20-snapshot.v20260716135136
@clerk/tanstack-react-start1.4.20-snapshot.v20260716135136
@clerk/testing2.2.10-snapshot.v20260716135136
@clerk/ui1.26.0-snapshot.v20260716135136
@clerk/upgrade2.0.5-snapshot.v20260716135136
@clerk/vue2.4.17-snapshot.v20260716135136

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

npm i @clerk/astro@3.4.19-snapshot.v20260716135136 --save-exact

@clerk/backend

npm i @clerk/backend@3.11.7-snapshot.v20260716135136 --save-exact

@clerk/chrome-extension

npm i @clerk/chrome-extension@3.1.54-snapshot.v20260716135136 --save-exact

@clerk/clerk-js

npm i @clerk/clerk-js@6.25.5-snapshot.v20260716135136 --save-exact

@clerk/electron

npm i @clerk/electron@0.0.15-snapshot.v20260716135136 --save-exact

@clerk/electron-passkeys

npm i @clerk/electron-passkeys@0.0.4-snapshot.v20260716135136 --save-exact

@clerk/eslint-plugin

npm i @clerk/eslint-plugin@0.2.1-snapshot.v20260716135136 --save-exact

@clerk/expo

npm i @clerk/expo@3.7.7-snapshot.v20260716135136 --save-exact

@clerk/expo-passkeys

npm i @clerk/expo-passkeys@1.2.6-snapshot.v20260716135136 --save-exact

@clerk/express

npm i @clerk/express@2.1.43-snapshot.v20260716135136 --save-exact

@clerk/fastify

npm i @clerk/fastify@3.1.53-snapshot.v20260716135136 --save-exact

@clerk/headless

npm i @clerk/headless@0.0.13-snapshot.v20260716135136 --save-exact

@clerk/hono

npm i @clerk/hono@0.1.53-snapshot.v20260716135136 --save-exact

@clerk/localizations

npm i @clerk/localizations@4.13.5-snapshot.v20260716135136 --save-exact

@clerk/msw

npm i @clerk/msw@0.0.49-snapshot.v20260716135136 --save-exact

@clerk/nextjs

npm i @clerk/nextjs@7.5.20-snapshot.v20260716135136 --save-exact

@clerk/nuxt

npm i @clerk/nuxt@2.6.19-snapshot.v20260716135136 --save-exact

@clerk/react

npm i @clerk/react@6.12.5-snapshot.v20260716135136 --save-exact

@clerk/react-router

npm i @clerk/react-router@3.5.12-snapshot.v20260716135136 --save-exact

@clerk/shared

npm i @clerk/shared@4.25.5-snapshot.v20260716135136 --save-exact

@clerk/swingset

npm i @clerk/swingset@0.0.20-snapshot.v20260716135136 --save-exact

@clerk/tanstack-react-start

npm i @clerk/tanstack-react-start@1.4.20-snapshot.v20260716135136 --save-exact

@clerk/testing

npm i @clerk/testing@2.2.10-snapshot.v20260716135136 --save-exact

@clerk/ui

npm i @clerk/ui@1.26.0-snapshot.v20260716135136 --save-exact

@clerk/upgrade

npm i @clerk/upgrade@2.0.5-snapshot.v20260716135136 --save-exact

@clerk/vue

npm i @clerk/vue@2.4.17-snapshot.v20260716135136 --save-exact

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (5)
packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx (1)

31-55: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Memoize the context value to avoid needless consumer re-renders.

orgProfileCtxValue (including a brand-new customPages: [] array) is recreated on every render and passed straight into OrganizationProfileContext.Provider. Any consumer relying on referential identity (e.g. a useEffect/useMemo dependency on customPages or the context object itself) will re-run needlessly on every re-render of this provider.

♻️ Suggested fix
- const orgProfileCtxValue = {- componentName: 'OrganizationProfile' as const,- mode: 'mounted' as const,- routing: 'hash' as const,- path: undefined,- afterLeaveOrganizationUrl,- apiKeysProps,- customPages: [],- };+ const orgProfileCtxValue = useMemo(+ () => ({+ componentName: 'OrganizationProfile' as const,+ mode: 'mounted' as const,+ routing: 'hash' as const,+ path: undefined,+ afterLeaveOrganizationUrl,+ apiKeysProps,+ customPages: [],+ }),+ [afterLeaveOrganizationUrl, apiKeysProps],+ );

As per coding guidelines, **/*.{tsx,jsx} should "Minimize re-renders in React components" and "Use proper useMemo for expensive computations in React components."

🤖 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/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx`
around lines 31 - 55, Memoize orgProfileCtxValue in OrganizationProfileProvider
so its object identity remains stable across renders, including the customPages
array. Use React’s memoization hook with dependencies covering
afterLeaveOrganizationUrl and apiKeysProps, while keeping the existing context
fields and provider behavior unchanged.

Source: Coding guidelines

packages/ui/src/experimental/index.ts (1)

10-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace the chained wildcard barrels with deliberate public exports.

The intermediate and published barrels together expose future symbols and collisions through @clerk/ui/experimental.

  • packages/ui/src/experimental/index.ts#L10-L10: explicitly export the supported experimental components from their leaf modules.
  • packages/ui/src/composed/index.ts#L1-L2: remove the intermediate wildcard aggregation or replace it with an explicit internal export list.

As per coding guidelines, “Avoid barrel files (index.ts re-exports) as they can cause circular dependencies.”

🤖 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/ui/src/experimental/index.ts` at line 10, Replace the wildcard
export in packages/ui/src/experimental/index.ts at line 10 with explicit exports
of the supported experimental components from their leaf modules. In
packages/ui/src/composed/index.ts at lines 1-2, remove the wildcard aggregation
or replace it with an explicit internal export list so future symbols and
collisions are not exposed.

Source: Coding guidelines

integration/tests/composed-components.test.ts (1)

31-45: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add an integration fixture without a local 'use client' boundary.

This page becomes a Client Component, so it cannot verify the advertised ability to import and render these exports directly from a React Server Component. Add a minimal server page that imports the experimental components and asserts they render.

As per coding guidelines, include tests for all new features.

🤖 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 `@integration/tests/composed-components.test.ts` around lines 31 - 45, Update
the composedUserProfilePage fixture to remove the local 'use client' directive
and keep it as a minimal React Server Component that imports and renders the
experimental UserProfile exports. Ensure the integration test asserts successful
rendering from this server page, covering the direct server-component import
path for all newly supported components.

Source: Coding guidelines

packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx (1)

18-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add explicit return types to exported components.

  • packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx#L18-L18: annotate the component return type.
  • packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx#L46-L46: annotate the newly exported component return type.
  • packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx#L26-L26: annotate the exported component return type.

As per coding guidelines, exported TypeScript APIs require explicit return types; based on learnings, this repository enforces that for exported functions.

🤖 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/ui/src/elements/ProfileCard/ProfilePagePanel.tsx` at line 18, Add
explicit return type annotations to the exported components ProfilePagePanel,
ConfigureSSO, and ProfileCardPage. Update each component declaration at
packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx:18-18,
packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx:46-46, and
packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx:26-26, using the
appropriate React component return type while preserving their existing
behavior.

Sources: Coding guidelines, Learnings

packages/ui/src/composed/UserProfile/UserProfileProvider.tsx (1)

29-37: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Memoize the context value to avoid re-rendering the whole composed subtree.

userProfileCtxValue is a new object every render, so all descendants consuming UserProfileContext re-render on every UserProfileProvider render regardless of whether any field changed. ProfileProviderShell already memoizes its comparable derived values (router, options), so this is inconsistent with the pattern elsewhere in the layer.

As per coding guidelines, "**/*.{jsx,tsx}": "Use proper useMemo for expensive computations in React components" and "Minimize re-renders in React components."

♻️ Proposed fix
+import { useMemo } from 'react';
...
- const userProfileCtxValue = {- componentName: 'UserProfile' as const,- mode: 'mounted' as const,- routing: 'hash' as const,- path: undefined,- additionalOAuthScopes,- apiKeysProps,- customPages: [],- };+ const userProfileCtxValue = useMemo(+ () => ({+ componentName: 'UserProfile' as const,+ mode: 'mounted' as const,+ routing: 'hash' as const,+ path: undefined,+ additionalOAuthScopes,+ apiKeysProps,+ customPages: [],+ }),+ [additionalOAuthScopes, apiKeysProps],+ );
🤖 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/ui/src/composed/UserProfile/UserProfileProvider.tsx` around lines 29
- 37, Memoize the userProfileCtxValue object in UserProfileProvider with
React.useMemo, using all values included in the context object—especially
additionalOAuthScopes and apiKeysProps—as dependencies; preserve the existing
constant fields and empty customPages value.

Source: Coding guidelines

🤖 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 `@integration/tests/composed-components.test.ts`:
- Around line 127-130: Update the afterAll cleanup blocks around fake users,
organizations, and related temporary entities to use try/finally so each entity
deletion is attempted safely and app.teardown() always runs independently of API
cleanup failures. Preserve the existing cleanup targets and ordering where
possible while ensuring failures in assertions or deletion do not prevent
subsequent cleanup.
In `@packages/ui/src/composed/__tests__/action-animation.test.tsx`:
- Around line 16-26: Replace any-based animation helper types with
Parameters<Element['animate']> call tuples and Keyframe/Keyframe[] types in
findAddAnimationCall and the corresponding helpers in
packages/ui/src/composed/__tests__/action-animation.test.tsx (lines 16-26) and
packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx (lines
28-48). In packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx
(lines 62-68), replace the as any mock result with an Animation-typed fixture or
narrow Partial<Animation> cast.
In `@packages/ui/src/styledSystem/createEmotionCache.ts`:
- Around line 3-4: Update the Emotion insert override in createEmotionCache so
its assigned function inherits cache.insert’s parameter types instead of
declaring an explicit any; keep sheet typed as Emotion’s StyleSheet and remove
the now-unused SerializedStyles import.
---
Nitpick comments:
In `@integration/tests/composed-components.test.ts`:
- Around line 31-45: Update the composedUserProfilePage fixture to remove the
local 'use client' directive and keep it as a minimal React Server Component
that imports and renders the experimental UserProfile exports. Ensure the
integration test asserts successful rendering from this server page, covering
the direct server-component import path for all newly supported components.
In
`@packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx`:
- Around line 31-55: Memoize orgProfileCtxValue in OrganizationProfileProvider
so its object identity remains stable across renders, including the customPages
array. Use React’s memoization hook with dependencies covering
afterLeaveOrganizationUrl and apiKeysProps, while keeping the existing context
fields and provider behavior unchanged.
In `@packages/ui/src/composed/UserProfile/UserProfileProvider.tsx`:
- Around line 29-37: Memoize the userProfileCtxValue object in
UserProfileProvider with React.useMemo, using all values included in the context
object—especially additionalOAuthScopes and apiKeysProps—as dependencies;
preserve the existing constant fields and empty customPages value.
In `@packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx`:
- Line 18: Add explicit return type annotations to the exported components
ProfilePagePanel, ConfigureSSO, and ProfileCardPage. Update each component
declaration at packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx:18-18,
packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx:46-46, and
packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx:26-26, using the
appropriate React component return type while preserving their existing
behavior.
In `@packages/ui/src/experimental/index.ts`:
- Line 10: Replace the wildcard export in packages/ui/src/experimental/index.ts
at line 10 with explicit exports of the supported experimental components from
their leaf modules. In packages/ui/src/composed/index.ts at lines 1-2, remove
the wildcard aggregation or replace it with an explicit internal export list so
future symbols and collisions are not exposed.
🪄 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 Plus

Run ID: 4b6a5164-137f-461f-85b0-6ad847013b23

📥 Commits

Reviewing files that changed from the base of the PR and between 430ae23 and 3464ff9.

⛔ Files ignored due to path filters (1)
  • packages/ui/src/experimental/__tests__/__snapshots__/flat-exports.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (85)
  • .changeset/profile-section-components.md
  • .changeset/shared-moduleManager-registry.md
  • integration/tests/composed-components.test.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/react/src/__tests__/isomorphicClerk.test.ts
  • packages/react/src/isomorphicClerk.ts
  • packages/shared/src/types/clerk.ts
  • packages/ui/package.json
  • packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationBillingPage.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationGeneralPage.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationMembers.tsx
  • packages/ui/src/components/UserProfile/APIKeysPage.tsx
  • packages/ui/src/components/UserProfile/AccountPage.tsx
  • packages/ui/src/components/UserProfile/AccountSections.tsx
  • packages/ui/src/components/UserProfile/BillingPage.tsx
  • packages/ui/src/components/UserProfile/SecurityPage.tsx
  • packages/ui/src/components/UserProfile/SecuritySections.tsx
  • packages/ui/src/components/UserProfile/Web3Form.tsx
  • packages/ui/src/components/UserProfile/__tests__/AccountSections.test.tsx
  • packages/ui/src/components/UserProfile/__tests__/SecuritySections.test.tsx
  • packages/ui/src/components/UserProfile/__tests__/Web3Section.test.tsx
  • packages/ui/src/composed/APIKeysSection.tsx
  • packages/ui/src/composed/BillingSection.tsx
  • packages/ui/src/composed/OrganizationProfile/APIKeys.tsx
  • packages/ui/src/composed/OrganizationProfile/Billing.tsx
  • packages/ui/src/composed/OrganizationProfile/General.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralDeleteOrganization.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralLeaveOrganization.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralOrganizationProfile.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralVerifiedDomains.tsx
  • packages/ui/src/composed/OrganizationProfile/Members.tsx
  • packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx
  • packages/ui/src/composed/OrganizationProfile/Security.tsx
  • packages/ui/src/composed/OrganizationProfile/index.tsx
  • packages/ui/src/composed/PageContext.tsx
  • packages/ui/src/composed/ProfileProviderShell.tsx
  • packages/ui/src/composed/UserProfile/APIKeys.tsx
  • packages/ui/src/composed/UserProfile/Account.tsx
  • packages/ui/src/composed/UserProfile/AccountConnectedAccounts.tsx
  • packages/ui/src/composed/UserProfile/AccountEmails.tsx
  • packages/ui/src/composed/UserProfile/AccountEnterpriseAccounts.tsx
  • packages/ui/src/composed/UserProfile/AccountPhone.tsx
  • packages/ui/src/composed/UserProfile/AccountProfile.tsx
  • packages/ui/src/composed/UserProfile/AccountUsername.tsx
  • packages/ui/src/composed/UserProfile/AccountWeb3.tsx
  • packages/ui/src/composed/UserProfile/Billing.tsx
  • packages/ui/src/composed/UserProfile/Security.tsx
  • packages/ui/src/composed/UserProfile/SecurityActiveDevices.tsx
  • packages/ui/src/composed/UserProfile/SecurityDelete.tsx
  • packages/ui/src/composed/UserProfile/SecurityMfa.tsx
  • packages/ui/src/composed/UserProfile/SecurityPasskeys.tsx
  • packages/ui/src/composed/UserProfile/SecurityPassword.tsx
  • packages/ui/src/composed/UserProfile/UserProfileProvider.tsx
  • packages/ui/src/composed/UserProfile/index.tsx
  • packages/ui/src/composed/__tests__/OrganizationProfile.test.tsx
  • packages/ui/src/composed/__tests__/OrganizationProfileSections.test.tsx
  • packages/ui/src/composed/__tests__/UserProfile.test.tsx
  • packages/ui/src/composed/__tests__/UserProfileSections.test.tsx
  • packages/ui/src/composed/__tests__/action-animation.test.tsx
  • packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx
  • packages/ui/src/composed/__tests__/composed-provider-wiring.test.tsx
  • packages/ui/src/composed/__tests__/hotload-vs-bundle-risks.test.tsx
  • packages/ui/src/composed/__tests__/stub-limitations.test.ts
  • packages/ui/src/composed/__tests__/style-cache-sharing.test.tsx
  • packages/ui/src/composed/createSection.tsx
  • packages/ui/src/composed/index.ts
  • packages/ui/src/composed/stubRouter.ts
  • packages/ui/src/composed/useBillingRouter.ts
  • packages/ui/src/composed/useRequirePage.ts
  • packages/ui/src/customizables/elementDescriptors.ts
  • packages/ui/src/elements/Animated.tsx
  • packages/ui/src/elements/AppearanceOverrides.tsx
  • packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx
  • packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx
  • packages/ui/src/elements/ProfileCard/__tests__/ProfilePagePanel.test.tsx
  • packages/ui/src/elements/ProfileCard/index.ts
  • packages/ui/src/experimental/__tests__/flat-exports.test.ts
  • packages/ui/src/experimental/index.ts
  • packages/ui/src/hooks/useSafeState.ts
  • packages/ui/src/internal/appearance.ts
  • packages/ui/src/internal/styleCacheStore.ts
  • packages/ui/src/styledSystem/StyleCacheProvider.tsx
  • packages/ui/src/styledSystem/createEmotionCache.ts
  • packages/ui/tsdown.config.mts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • clerk/clerk_go(manual)
  • clerk/dashboard(manual)
  • clerk/accounts(manual)
  • clerk/backoffice(manual)
  • clerk/clerk(manual)
  • clerk/clerk-docs(manual)
  • clerk/cloudflare-workers(manual)

Comment threadintegration/tests/composed-components.test.ts
Comment threadpackages/ui/src/composed/__tests__/action-animation.test.tsx Outdated
Comment threadpackages/ui/src/styledSystem/createEmotionCache.ts Outdated
- Remove `any` from createEmotionCache insert override and animation test helpers
- Type animation call tuples via Parameters<Element['animate']>
- Make integration test cleanup failure-safe with try/finally
@alexcarpenteralexcarpenter changed the title feat(ui): composed profile components (release)feat(ui): Expose composed profile componentsJul 22, 2026
@alexcarpenter
alexcarpenter merged commit 01f2c12 into mainJul 24, 2026
55 checks passed
@alexcarpenter
alexcarpenter deleted the carp/profile-release branch July 24, 2026 13:30
Sign up for freeto 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.

2 participants

@alexcarpenter@brkalow
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(ui): Expose composed profile components by alexcarpenter · Pull Request #9144 · clerk/javascript · GitHub
Skip to content

feat(ui): Expose composed profile components - #9144

Merged
alexcarpenter merged 11 commits into
mainfrom
carp/profile-release
Jul 24, 2026
Merged

feat(ui): Expose composed profile components#9144
alexcarpenter merged 11 commits into
mainfrom
carp/profile-release

Conversation

@alexcarpenter

@alexcarpenteralexcarpenter commented Jul 13, 2026

Copy link
Copy Markdown
Member

Ships the experimental composed profile API under @clerk/ui/experimental. Lets developers build the profile UI from flat, individually-mountable panel and section components instead of the monolithic <UserProfile /> / <OrganizationProfile />. Each export is a top-level client reference, so it renders directly in an RSC tree without a consumer 'use client' boundary.

What this exposes

New entrypoint: @clerk/ui/experimental.

UserProfile

  • Provider: UserProfileProvider
  • Panels: UserProfileAccountPanel, UserProfileSecurityPanel, UserProfileBillingPanel, UserProfileAPIKeysPanel
  • Account sections: UserProfileProfileSection, UserProfileUsernameSection, UserProfileEmailSection, UserProfilePhoneSection, UserProfileConnectedAccountsSection, UserProfileEnterpriseAccountsSection, UserProfileWeb3Section
  • Security sections: UserProfilePasswordSection, UserProfilePasskeysSection, UserProfileMfaSection, UserProfileActiveDevicesSection, UserProfileDeleteSection

OrganizationProfile

  • Provider: OrganizationProfileProvider
  • Panels: OrganizationProfileGeneralPanel, OrganizationProfileMembersPanel, OrganizationProfileBillingPanel, OrganizationProfileAPIKeysPanel, OrganizationProfileSecurityPanel
  • Sections: OrganizationProfileProfileSection, OrganizationProfileDomainsSection, OrganizationProfileLeaveSection, OrganizationProfileDeleteSection

Section wrappers render the same underlying components as standard <UserProfile /> / <OrganizationProfile />, so behavior matches; E2E parity coverage added.

Experimental: API may change; gated behind the /experimental entrypoint.

@vercel

vercelBot commented Jul 13, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
clerk-js-sandboxReadyReadyPreview, CommentJul 21, 2026 11:31pm
swingsetReadyReadyPreview, CommentJul 21, 2026 11:31pm

Request Review

@changeset-bot

changeset-botBot commented Jul 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: cd3228b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 23 packages
NameType
@clerk/uiMinor
@clerk/clerk-jsPatch
@clerk/sharedPatch
@clerk/reactPatch
@clerk/astroPatch
@clerk/chrome-extensionPatch
@clerk/swingsetPatch
@clerk/vuePatch
@clerk/electronPatch
@clerk/expoPatch
@clerk/backendPatch
@clerk/expo-passkeysPatch
@clerk/expressPatch
@clerk/fastifyPatch
@clerk/headlessPatch
@clerk/honoPatch
@clerk/localizationsPatch
@clerk/mswPatch
@clerk/nextjsPatch
@clerk/nuxtPatch
@clerk/react-routerPatch
@clerk/tanstack-react-startPatch
@clerk/testingPatch

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

@coderabbitai

coderabbitaiBot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change introduces experimental composable UserProfile and OrganizationProfile exports through @clerk/ui/experimental. It adds providers, panels, sections, routing, runtime module-manager access, shared style-cache handling, profile layout primitives, and conditional rendering logic. It also refactors account and security pages, improves Web3 error handling and animation lifecycle management, and adds unit, Vitest, and Playwright coverage for composed flows and exports.

Estimated code review effort: 5 (Critical) | ~120 minutes

Suggested reviewers:brkalow

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 8.70% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Title check✅ PassedThe title clearly summarizes the main change: exposing composed profile components in the UI package.
Description check✅ PassedThe description matches the changeset by documenting the experimental composed profile API and its exported panels and sections.

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

@pkg-pr-new

pkg-pr-newBot commented Jul 13, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

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

@clerk/backend

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

@clerk/chrome-extension

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

@clerk/clerk-js

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

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@9144

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@9144

@clerk/eslint-plugin

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

@clerk/expo

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

@clerk/expo-google-signin

npm i https://pkg.pr.new/@clerk/expo-google-signin@9144

@clerk/expo-passkeys

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

@clerk/express

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

@clerk/fastify

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

@clerk/hono

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

@clerk/localizations

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

@clerk/nextjs

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

@clerk/nuxt

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

@clerk/react

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

@clerk/react-router

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

@clerk/shared

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

@clerk/tanstack-react-start

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

@clerk/testing

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

@clerk/ui

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

@clerk/upgrade

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

@clerk/vue

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

commit: cd3228b

@github-actions

github-actionsBot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

API Changes Report

Generated by Break Check on 2026-07-21T23:33:34.901Z

Summary

MetricCount
Packages analyzed19
Packages with changes1
🔴 Breaking changes0
🟡 Non-breaking changes1
🟢 Additions1

🤖 This report was reviewed by claude-sonnet-4-6.


@clerk/ui

Current version: 1.25.6
Recommended bump: MINOR → 1.26.0

Subpath ./experimental

🟢 Additions (1)

Added: ./experimental

New subpath export ./experimental (27 exported members)

Subpath ./internal

🟡 Non-breaking Changes (1)

Modified: ElementsConfig
// ... 391 unchanged lines elided ...
profileSectionPrimaryButton: WithOptions<ProfileSectionId>;
profileSectionButtonGroup: WithOptions<ProfileSectionId>;
profilePage: WithOptions<ProfilePageId>;
+ profilePageContent: WithOptions;
formattedPhoneNumber: WithOptions;
formattedPhoneNumberFlag: WithOptions;
formattedPhoneNumberText: WithOptions;
// ... 158 unchanged lines elided ...

Static analyzer: Breaking change in type alias ElementsConfig: Type changed: {button:import("@clerk/ui").~WithOptions<string>;input:import("@clerk/ui").~WithOptions;checkbox:import("@clerk/ui").~W…{button:import("@clerk/ui").~WithOptions<string>;input:import("@clerk/ui").~WithOptions;checkbox:import("@clerk/ui").~W…

🤖 AI review (reclassified as non-breaking) (85%): The elided section grew by exactly one line (475 → 476), indicating a new key was added to ElementsConfig; ElementsConfig is used only as a mapped-type source for the output type Elements, so consumers never construct values of this type directly — adding a new output-only property is non-breaking.


Report generated by Break Check

Last ran on cd3228b.

@alexcarpenter

Copy link
Copy Markdown
MemberAuthor

!snapshot

@github-actions

Copy link
Copy Markdown
Contributor

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

PackageVersion
@clerk/astro3.4.19-snapshot.v20260716135136
@clerk/backend3.11.7-snapshot.v20260716135136
@clerk/chrome-extension3.1.54-snapshot.v20260716135136
@clerk/clerk-js6.25.5-snapshot.v20260716135136
@clerk/electron0.0.15-snapshot.v20260716135136
@clerk/electron-passkeys0.0.4-snapshot.v20260716135136
@clerk/eslint-plugin0.2.1-snapshot.v20260716135136
@clerk/expo3.7.7-snapshot.v20260716135136
@clerk/expo-passkeys1.2.6-snapshot.v20260716135136
@clerk/express2.1.43-snapshot.v20260716135136
@clerk/fastify3.1.53-snapshot.v20260716135136
@clerk/headless0.0.13-snapshot.v20260716135136
@clerk/hono0.1.53-snapshot.v20260716135136
@clerk/localizations4.13.5-snapshot.v20260716135136
@clerk/msw0.0.49-snapshot.v20260716135136
@clerk/nextjs7.5.20-snapshot.v20260716135136
@clerk/nuxt2.6.19-snapshot.v20260716135136
@clerk/react6.12.5-snapshot.v20260716135136
@clerk/react-router3.5.12-snapshot.v20260716135136
@clerk/shared4.25.5-snapshot.v20260716135136
@clerk/swingset0.0.20-snapshot.v20260716135136
@clerk/tanstack-react-start1.4.20-snapshot.v20260716135136
@clerk/testing2.2.10-snapshot.v20260716135136
@clerk/ui1.26.0-snapshot.v20260716135136
@clerk/upgrade2.0.5-snapshot.v20260716135136
@clerk/vue2.4.17-snapshot.v20260716135136

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

npm i @clerk/astro@3.4.19-snapshot.v20260716135136 --save-exact

@clerk/backend

npm i @clerk/backend@3.11.7-snapshot.v20260716135136 --save-exact

@clerk/chrome-extension

npm i @clerk/chrome-extension@3.1.54-snapshot.v20260716135136 --save-exact

@clerk/clerk-js

npm i @clerk/clerk-js@6.25.5-snapshot.v20260716135136 --save-exact

@clerk/electron

npm i @clerk/electron@0.0.15-snapshot.v20260716135136 --save-exact

@clerk/electron-passkeys

npm i @clerk/electron-passkeys@0.0.4-snapshot.v20260716135136 --save-exact

@clerk/eslint-plugin

npm i @clerk/eslint-plugin@0.2.1-snapshot.v20260716135136 --save-exact

@clerk/expo

npm i @clerk/expo@3.7.7-snapshot.v20260716135136 --save-exact

@clerk/expo-passkeys

npm i @clerk/expo-passkeys@1.2.6-snapshot.v20260716135136 --save-exact

@clerk/express

npm i @clerk/express@2.1.43-snapshot.v20260716135136 --save-exact

@clerk/fastify

npm i @clerk/fastify@3.1.53-snapshot.v20260716135136 --save-exact

@clerk/headless

npm i @clerk/headless@0.0.13-snapshot.v20260716135136 --save-exact

@clerk/hono

npm i @clerk/hono@0.1.53-snapshot.v20260716135136 --save-exact

@clerk/localizations

npm i @clerk/localizations@4.13.5-snapshot.v20260716135136 --save-exact

@clerk/msw

npm i @clerk/msw@0.0.49-snapshot.v20260716135136 --save-exact

@clerk/nextjs

npm i @clerk/nextjs@7.5.20-snapshot.v20260716135136 --save-exact

@clerk/nuxt

npm i @clerk/nuxt@2.6.19-snapshot.v20260716135136 --save-exact

@clerk/react

npm i @clerk/react@6.12.5-snapshot.v20260716135136 --save-exact

@clerk/react-router

npm i @clerk/react-router@3.5.12-snapshot.v20260716135136 --save-exact

@clerk/shared

npm i @clerk/shared@4.25.5-snapshot.v20260716135136 --save-exact

@clerk/swingset

npm i @clerk/swingset@0.0.20-snapshot.v20260716135136 --save-exact

@clerk/tanstack-react-start

npm i @clerk/tanstack-react-start@1.4.20-snapshot.v20260716135136 --save-exact

@clerk/testing

npm i @clerk/testing@2.2.10-snapshot.v20260716135136 --save-exact

@clerk/ui

npm i @clerk/ui@1.26.0-snapshot.v20260716135136 --save-exact

@clerk/upgrade

npm i @clerk/upgrade@2.0.5-snapshot.v20260716135136 --save-exact

@clerk/vue

npm i @clerk/vue@2.4.17-snapshot.v20260716135136 --save-exact

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (5)
packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx (1)

31-55: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Memoize the context value to avoid needless consumer re-renders.

orgProfileCtxValue (including a brand-new customPages: [] array) is recreated on every render and passed straight into OrganizationProfileContext.Provider. Any consumer relying on referential identity (e.g. a useEffect/useMemo dependency on customPages or the context object itself) will re-run needlessly on every re-render of this provider.

♻️ Suggested fix
- const orgProfileCtxValue = {- componentName: 'OrganizationProfile' as const,- mode: 'mounted' as const,- routing: 'hash' as const,- path: undefined,- afterLeaveOrganizationUrl,- apiKeysProps,- customPages: [],- };+ const orgProfileCtxValue = useMemo(+ () => ({+ componentName: 'OrganizationProfile' as const,+ mode: 'mounted' as const,+ routing: 'hash' as const,+ path: undefined,+ afterLeaveOrganizationUrl,+ apiKeysProps,+ customPages: [],+ }),+ [afterLeaveOrganizationUrl, apiKeysProps],+ );

As per coding guidelines, **/*.{tsx,jsx} should "Minimize re-renders in React components" and "Use proper useMemo for expensive computations in React components."

🤖 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/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx`
around lines 31 - 55, Memoize orgProfileCtxValue in OrganizationProfileProvider
so its object identity remains stable across renders, including the customPages
array. Use React’s memoization hook with dependencies covering
afterLeaveOrganizationUrl and apiKeysProps, while keeping the existing context
fields and provider behavior unchanged.

Source: Coding guidelines

packages/ui/src/experimental/index.ts (1)

10-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace the chained wildcard barrels with deliberate public exports.

The intermediate and published barrels together expose future symbols and collisions through @clerk/ui/experimental.

  • packages/ui/src/experimental/index.ts#L10-L10: explicitly export the supported experimental components from their leaf modules.
  • packages/ui/src/composed/index.ts#L1-L2: remove the intermediate wildcard aggregation or replace it with an explicit internal export list.

As per coding guidelines, “Avoid barrel files (index.ts re-exports) as they can cause circular dependencies.”

🤖 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/ui/src/experimental/index.ts` at line 10, Replace the wildcard
export in packages/ui/src/experimental/index.ts at line 10 with explicit exports
of the supported experimental components from their leaf modules. In
packages/ui/src/composed/index.ts at lines 1-2, remove the wildcard aggregation
or replace it with an explicit internal export list so future symbols and
collisions are not exposed.

Source: Coding guidelines

integration/tests/composed-components.test.ts (1)

31-45: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add an integration fixture without a local 'use client' boundary.

This page becomes a Client Component, so it cannot verify the advertised ability to import and render these exports directly from a React Server Component. Add a minimal server page that imports the experimental components and asserts they render.

As per coding guidelines, include tests for all new features.

🤖 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 `@integration/tests/composed-components.test.ts` around lines 31 - 45, Update
the composedUserProfilePage fixture to remove the local 'use client' directive
and keep it as a minimal React Server Component that imports and renders the
experimental UserProfile exports. Ensure the integration test asserts successful
rendering from this server page, covering the direct server-component import
path for all newly supported components.

Source: Coding guidelines

packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx (1)

18-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add explicit return types to exported components.

  • packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx#L18-L18: annotate the component return type.
  • packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx#L46-L46: annotate the newly exported component return type.
  • packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx#L26-L26: annotate the exported component return type.

As per coding guidelines, exported TypeScript APIs require explicit return types; based on learnings, this repository enforces that for exported functions.

🤖 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/ui/src/elements/ProfileCard/ProfilePagePanel.tsx` at line 18, Add
explicit return type annotations to the exported components ProfilePagePanel,
ConfigureSSO, and ProfileCardPage. Update each component declaration at
packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx:18-18,
packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx:46-46, and
packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx:26-26, using the
appropriate React component return type while preserving their existing
behavior.

Sources: Coding guidelines, Learnings

packages/ui/src/composed/UserProfile/UserProfileProvider.tsx (1)

29-37: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Memoize the context value to avoid re-rendering the whole composed subtree.

userProfileCtxValue is a new object every render, so all descendants consuming UserProfileContext re-render on every UserProfileProvider render regardless of whether any field changed. ProfileProviderShell already memoizes its comparable derived values (router, options), so this is inconsistent with the pattern elsewhere in the layer.

As per coding guidelines, "**/*.{jsx,tsx}": "Use proper useMemo for expensive computations in React components" and "Minimize re-renders in React components."

♻️ Proposed fix
+import { useMemo } from 'react';
...
- const userProfileCtxValue = {- componentName: 'UserProfile' as const,- mode: 'mounted' as const,- routing: 'hash' as const,- path: undefined,- additionalOAuthScopes,- apiKeysProps,- customPages: [],- };+ const userProfileCtxValue = useMemo(+ () => ({+ componentName: 'UserProfile' as const,+ mode: 'mounted' as const,+ routing: 'hash' as const,+ path: undefined,+ additionalOAuthScopes,+ apiKeysProps,+ customPages: [],+ }),+ [additionalOAuthScopes, apiKeysProps],+ );
🤖 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/ui/src/composed/UserProfile/UserProfileProvider.tsx` around lines 29
- 37, Memoize the userProfileCtxValue object in UserProfileProvider with
React.useMemo, using all values included in the context object—especially
additionalOAuthScopes and apiKeysProps—as dependencies; preserve the existing
constant fields and empty customPages value.

Source: Coding guidelines

🤖 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 `@integration/tests/composed-components.test.ts`:
- Around line 127-130: Update the afterAll cleanup blocks around fake users,
organizations, and related temporary entities to use try/finally so each entity
deletion is attempted safely and app.teardown() always runs independently of API
cleanup failures. Preserve the existing cleanup targets and ordering where
possible while ensuring failures in assertions or deletion do not prevent
subsequent cleanup.
In `@packages/ui/src/composed/__tests__/action-animation.test.tsx`:
- Around line 16-26: Replace any-based animation helper types with
Parameters<Element['animate']> call tuples and Keyframe/Keyframe[] types in
findAddAnimationCall and the corresponding helpers in
packages/ui/src/composed/__tests__/action-animation.test.tsx (lines 16-26) and
packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx (lines
28-48). In packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx
(lines 62-68), replace the as any mock result with an Animation-typed fixture or
narrow Partial<Animation> cast.
In `@packages/ui/src/styledSystem/createEmotionCache.ts`:
- Around line 3-4: Update the Emotion insert override in createEmotionCache so
its assigned function inherits cache.insert’s parameter types instead of
declaring an explicit any; keep sheet typed as Emotion’s StyleSheet and remove
the now-unused SerializedStyles import.
---
Nitpick comments:
In `@integration/tests/composed-components.test.ts`:
- Around line 31-45: Update the composedUserProfilePage fixture to remove the
local 'use client' directive and keep it as a minimal React Server Component
that imports and renders the experimental UserProfile exports. Ensure the
integration test asserts successful rendering from this server page, covering
the direct server-component import path for all newly supported components.
In
`@packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx`:
- Around line 31-55: Memoize orgProfileCtxValue in OrganizationProfileProvider
so its object identity remains stable across renders, including the customPages
array. Use React’s memoization hook with dependencies covering
afterLeaveOrganizationUrl and apiKeysProps, while keeping the existing context
fields and provider behavior unchanged.
In `@packages/ui/src/composed/UserProfile/UserProfileProvider.tsx`:
- Around line 29-37: Memoize the userProfileCtxValue object in
UserProfileProvider with React.useMemo, using all values included in the context
object—especially additionalOAuthScopes and apiKeysProps—as dependencies;
preserve the existing constant fields and empty customPages value.
In `@packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx`:
- Line 18: Add explicit return type annotations to the exported components
ProfilePagePanel, ConfigureSSO, and ProfileCardPage. Update each component
declaration at packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx:18-18,
packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx:46-46, and
packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx:26-26, using the
appropriate React component return type while preserving their existing
behavior.
In `@packages/ui/src/experimental/index.ts`:
- Line 10: Replace the wildcard export in packages/ui/src/experimental/index.ts
at line 10 with explicit exports of the supported experimental components from
their leaf modules. In packages/ui/src/composed/index.ts at lines 1-2, remove
the wildcard aggregation or replace it with an explicit internal export list so
future symbols and collisions are not exposed.
🪄 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 Plus

Run ID: 4b6a5164-137f-461f-85b0-6ad847013b23

📥 Commits

Reviewing files that changed from the base of the PR and between 430ae23 and 3464ff9.

⛔ Files ignored due to path filters (1)
  • packages/ui/src/experimental/__tests__/__snapshots__/flat-exports.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (85)
  • .changeset/profile-section-components.md
  • .changeset/shared-moduleManager-registry.md
  • integration/tests/composed-components.test.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/react/src/__tests__/isomorphicClerk.test.ts
  • packages/react/src/isomorphicClerk.ts
  • packages/shared/src/types/clerk.ts
  • packages/ui/package.json
  • packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationBillingPage.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationGeneralPage.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationMembers.tsx
  • packages/ui/src/components/UserProfile/APIKeysPage.tsx
  • packages/ui/src/components/UserProfile/AccountPage.tsx
  • packages/ui/src/components/UserProfile/AccountSections.tsx
  • packages/ui/src/components/UserProfile/BillingPage.tsx
  • packages/ui/src/components/UserProfile/SecurityPage.tsx
  • packages/ui/src/components/UserProfile/SecuritySections.tsx
  • packages/ui/src/components/UserProfile/Web3Form.tsx
  • packages/ui/src/components/UserProfile/__tests__/AccountSections.test.tsx
  • packages/ui/src/components/UserProfile/__tests__/SecuritySections.test.tsx
  • packages/ui/src/components/UserProfile/__tests__/Web3Section.test.tsx
  • packages/ui/src/composed/APIKeysSection.tsx
  • packages/ui/src/composed/BillingSection.tsx
  • packages/ui/src/composed/OrganizationProfile/APIKeys.tsx
  • packages/ui/src/composed/OrganizationProfile/Billing.tsx
  • packages/ui/src/composed/OrganizationProfile/General.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralDeleteOrganization.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralLeaveOrganization.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralOrganizationProfile.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralVerifiedDomains.tsx
  • packages/ui/src/composed/OrganizationProfile/Members.tsx
  • packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx
  • packages/ui/src/composed/OrganizationProfile/Security.tsx
  • packages/ui/src/composed/OrganizationProfile/index.tsx
  • packages/ui/src/composed/PageContext.tsx
  • packages/ui/src/composed/ProfileProviderShell.tsx
  • packages/ui/src/composed/UserProfile/APIKeys.tsx
  • packages/ui/src/composed/UserProfile/Account.tsx
  • packages/ui/src/composed/UserProfile/AccountConnectedAccounts.tsx
  • packages/ui/src/composed/UserProfile/AccountEmails.tsx
  • packages/ui/src/composed/UserProfile/AccountEnterpriseAccounts.tsx
  • packages/ui/src/composed/UserProfile/AccountPhone.tsx
  • packages/ui/src/composed/UserProfile/AccountProfile.tsx
  • packages/ui/src/composed/UserProfile/AccountUsername.tsx
  • packages/ui/src/composed/UserProfile/AccountWeb3.tsx
  • packages/ui/src/composed/UserProfile/Billing.tsx
  • packages/ui/src/composed/UserProfile/Security.tsx
  • packages/ui/src/composed/UserProfile/SecurityActiveDevices.tsx
  • packages/ui/src/composed/UserProfile/SecurityDelete.tsx
  • packages/ui/src/composed/UserProfile/SecurityMfa.tsx
  • packages/ui/src/composed/UserProfile/SecurityPasskeys.tsx
  • packages/ui/src/composed/UserProfile/SecurityPassword.tsx
  • packages/ui/src/composed/UserProfile/UserProfileProvider.tsx
  • packages/ui/src/composed/UserProfile/index.tsx
  • packages/ui/src/composed/__tests__/OrganizationProfile.test.tsx
  • packages/ui/src/composed/__tests__/OrganizationProfileSections.test.tsx
  • packages/ui/src/composed/__tests__/UserProfile.test.tsx
  • packages/ui/src/composed/__tests__/UserProfileSections.test.tsx
  • packages/ui/src/composed/__tests__/action-animation.test.tsx
  • packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx
  • packages/ui/src/composed/__tests__/composed-provider-wiring.test.tsx
  • packages/ui/src/composed/__tests__/hotload-vs-bundle-risks.test.tsx
  • packages/ui/src/composed/__tests__/stub-limitations.test.ts
  • packages/ui/src/composed/__tests__/style-cache-sharing.test.tsx
  • packages/ui/src/composed/createSection.tsx
  • packages/ui/src/composed/index.ts
  • packages/ui/src/composed/stubRouter.ts
  • packages/ui/src/composed/useBillingRouter.ts
  • packages/ui/src/composed/useRequirePage.ts
  • packages/ui/src/customizables/elementDescriptors.ts
  • packages/ui/src/elements/Animated.tsx
  • packages/ui/src/elements/AppearanceOverrides.tsx
  • packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx
  • packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx
  • packages/ui/src/elements/ProfileCard/__tests__/ProfilePagePanel.test.tsx
  • packages/ui/src/elements/ProfileCard/index.ts
  • packages/ui/src/experimental/__tests__/flat-exports.test.ts
  • packages/ui/src/experimental/index.ts
  • packages/ui/src/hooks/useSafeState.ts
  • packages/ui/src/internal/appearance.ts
  • packages/ui/src/internal/styleCacheStore.ts
  • packages/ui/src/styledSystem/StyleCacheProvider.tsx
  • packages/ui/src/styledSystem/createEmotionCache.ts
  • packages/ui/tsdown.config.mts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • clerk/clerk_go(manual)
  • clerk/dashboard(manual)
  • clerk/accounts(manual)
  • clerk/backoffice(manual)
  • clerk/clerk(manual)
  • clerk/clerk-docs(manual)
  • clerk/cloudflare-workers(manual)

Comment threadintegration/tests/composed-components.test.ts
Comment threadpackages/ui/src/composed/__tests__/action-animation.test.tsx Outdated
Comment threadpackages/ui/src/styledSystem/createEmotionCache.ts Outdated
- Remove `any` from createEmotionCache insert override and animation test helpers
- Type animation call tuples via Parameters<Element['animate']>
- Make integration test cleanup failure-safe with try/finally
@alexcarpenteralexcarpenter changed the title feat(ui): composed profile components (release)feat(ui): Expose composed profile componentsJul 22, 2026
@alexcarpenter
alexcarpenter merged commit 01f2c12 into mainJul 24, 2026
55 checks passed
@alexcarpenter
alexcarpenter deleted the carp/profile-release branch July 24, 2026 13:30
Sign up for freeto 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.

2 participants

@alexcarpenter@brkalow
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(ui): Expose composed profile components by alexcarpenter · Pull Request #9144 · clerk/javascript · GitHub
Skip to content

feat(ui): Expose composed profile components - #9144

Merged
alexcarpenter merged 11 commits into
mainfrom
carp/profile-release
Jul 24, 2026
Merged

feat(ui): Expose composed profile components#9144
alexcarpenter merged 11 commits into
mainfrom
carp/profile-release

Conversation

@alexcarpenter

@alexcarpenteralexcarpenter commented Jul 13, 2026

Copy link
Copy Markdown
Member

Ships the experimental composed profile API under @clerk/ui/experimental. Lets developers build the profile UI from flat, individually-mountable panel and section components instead of the monolithic <UserProfile /> / <OrganizationProfile />. Each export is a top-level client reference, so it renders directly in an RSC tree without a consumer 'use client' boundary.

What this exposes

New entrypoint: @clerk/ui/experimental.

UserProfile

  • Provider: UserProfileProvider
  • Panels: UserProfileAccountPanel, UserProfileSecurityPanel, UserProfileBillingPanel, UserProfileAPIKeysPanel
  • Account sections: UserProfileProfileSection, UserProfileUsernameSection, UserProfileEmailSection, UserProfilePhoneSection, UserProfileConnectedAccountsSection, UserProfileEnterpriseAccountsSection, UserProfileWeb3Section
  • Security sections: UserProfilePasswordSection, UserProfilePasskeysSection, UserProfileMfaSection, UserProfileActiveDevicesSection, UserProfileDeleteSection

OrganizationProfile

  • Provider: OrganizationProfileProvider
  • Panels: OrganizationProfileGeneralPanel, OrganizationProfileMembersPanel, OrganizationProfileBillingPanel, OrganizationProfileAPIKeysPanel, OrganizationProfileSecurityPanel
  • Sections: OrganizationProfileProfileSection, OrganizationProfileDomainsSection, OrganizationProfileLeaveSection, OrganizationProfileDeleteSection

Section wrappers render the same underlying components as standard <UserProfile /> / <OrganizationProfile />, so behavior matches; E2E parity coverage added.

Experimental: API may change; gated behind the /experimental entrypoint.

@vercel

vercelBot commented Jul 13, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
clerk-js-sandboxReadyReadyPreview, CommentJul 21, 2026 11:31pm
swingsetReadyReadyPreview, CommentJul 21, 2026 11:31pm

Request Review

@changeset-bot

changeset-botBot commented Jul 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: cd3228b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 23 packages
NameType
@clerk/uiMinor
@clerk/clerk-jsPatch
@clerk/sharedPatch
@clerk/reactPatch
@clerk/astroPatch
@clerk/chrome-extensionPatch
@clerk/swingsetPatch
@clerk/vuePatch
@clerk/electronPatch
@clerk/expoPatch
@clerk/backendPatch
@clerk/expo-passkeysPatch
@clerk/expressPatch
@clerk/fastifyPatch
@clerk/headlessPatch
@clerk/honoPatch
@clerk/localizationsPatch
@clerk/mswPatch
@clerk/nextjsPatch
@clerk/nuxtPatch
@clerk/react-routerPatch
@clerk/tanstack-react-startPatch
@clerk/testingPatch

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

@coderabbitai

coderabbitaiBot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change introduces experimental composable UserProfile and OrganizationProfile exports through @clerk/ui/experimental. It adds providers, panels, sections, routing, runtime module-manager access, shared style-cache handling, profile layout primitives, and conditional rendering logic. It also refactors account and security pages, improves Web3 error handling and animation lifecycle management, and adds unit, Vitest, and Playwright coverage for composed flows and exports.

Estimated code review effort: 5 (Critical) | ~120 minutes

Suggested reviewers:brkalow

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 8.70% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Title check✅ PassedThe title clearly summarizes the main change: exposing composed profile components in the UI package.
Description check✅ PassedThe description matches the changeset by documenting the experimental composed profile API and its exported panels and sections.

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

@pkg-pr-new

pkg-pr-newBot commented Jul 13, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

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

@clerk/backend

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

@clerk/chrome-extension

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

@clerk/clerk-js

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

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@9144

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@9144

@clerk/eslint-plugin

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

@clerk/expo

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

@clerk/expo-google-signin

npm i https://pkg.pr.new/@clerk/expo-google-signin@9144

@clerk/expo-passkeys

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

@clerk/express

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

@clerk/fastify

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

@clerk/hono

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

@clerk/localizations

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

@clerk/nextjs

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

@clerk/nuxt

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

@clerk/react

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

@clerk/react-router

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

@clerk/shared

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

@clerk/tanstack-react-start

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

@clerk/testing

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

@clerk/ui

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

@clerk/upgrade

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

@clerk/vue

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

commit: cd3228b

@github-actions

github-actionsBot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

API Changes Report

Generated by Break Check on 2026-07-21T23:33:34.901Z

Summary

MetricCount
Packages analyzed19
Packages with changes1
🔴 Breaking changes0
🟡 Non-breaking changes1
🟢 Additions1

🤖 This report was reviewed by claude-sonnet-4-6.


@clerk/ui

Current version: 1.25.6
Recommended bump: MINOR → 1.26.0

Subpath ./experimental

🟢 Additions (1)

Added: ./experimental

New subpath export ./experimental (27 exported members)

Subpath ./internal

🟡 Non-breaking Changes (1)

Modified: ElementsConfig
// ... 391 unchanged lines elided ...
profileSectionPrimaryButton: WithOptions<ProfileSectionId>;
profileSectionButtonGroup: WithOptions<ProfileSectionId>;
profilePage: WithOptions<ProfilePageId>;
+ profilePageContent: WithOptions;
formattedPhoneNumber: WithOptions;
formattedPhoneNumberFlag: WithOptions;
formattedPhoneNumberText: WithOptions;
// ... 158 unchanged lines elided ...

Static analyzer: Breaking change in type alias ElementsConfig: Type changed: {button:import("@clerk/ui").~WithOptions<string>;input:import("@clerk/ui").~WithOptions;checkbox:import("@clerk/ui").~W…{button:import("@clerk/ui").~WithOptions<string>;input:import("@clerk/ui").~WithOptions;checkbox:import("@clerk/ui").~W…

🤖 AI review (reclassified as non-breaking) (85%): The elided section grew by exactly one line (475 → 476), indicating a new key was added to ElementsConfig; ElementsConfig is used only as a mapped-type source for the output type Elements, so consumers never construct values of this type directly — adding a new output-only property is non-breaking.


Report generated by Break Check

Last ran on cd3228b.

@alexcarpenter

Copy link
Copy Markdown
MemberAuthor

!snapshot

@github-actions

Copy link
Copy Markdown
Contributor

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

PackageVersion
@clerk/astro3.4.19-snapshot.v20260716135136
@clerk/backend3.11.7-snapshot.v20260716135136
@clerk/chrome-extension3.1.54-snapshot.v20260716135136
@clerk/clerk-js6.25.5-snapshot.v20260716135136
@clerk/electron0.0.15-snapshot.v20260716135136
@clerk/electron-passkeys0.0.4-snapshot.v20260716135136
@clerk/eslint-plugin0.2.1-snapshot.v20260716135136
@clerk/expo3.7.7-snapshot.v20260716135136
@clerk/expo-passkeys1.2.6-snapshot.v20260716135136
@clerk/express2.1.43-snapshot.v20260716135136
@clerk/fastify3.1.53-snapshot.v20260716135136
@clerk/headless0.0.13-snapshot.v20260716135136
@clerk/hono0.1.53-snapshot.v20260716135136
@clerk/localizations4.13.5-snapshot.v20260716135136
@clerk/msw0.0.49-snapshot.v20260716135136
@clerk/nextjs7.5.20-snapshot.v20260716135136
@clerk/nuxt2.6.19-snapshot.v20260716135136
@clerk/react6.12.5-snapshot.v20260716135136
@clerk/react-router3.5.12-snapshot.v20260716135136
@clerk/shared4.25.5-snapshot.v20260716135136
@clerk/swingset0.0.20-snapshot.v20260716135136
@clerk/tanstack-react-start1.4.20-snapshot.v20260716135136
@clerk/testing2.2.10-snapshot.v20260716135136
@clerk/ui1.26.0-snapshot.v20260716135136
@clerk/upgrade2.0.5-snapshot.v20260716135136
@clerk/vue2.4.17-snapshot.v20260716135136

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

npm i @clerk/astro@3.4.19-snapshot.v20260716135136 --save-exact

@clerk/backend

npm i @clerk/backend@3.11.7-snapshot.v20260716135136 --save-exact

@clerk/chrome-extension

npm i @clerk/chrome-extension@3.1.54-snapshot.v20260716135136 --save-exact

@clerk/clerk-js

npm i @clerk/clerk-js@6.25.5-snapshot.v20260716135136 --save-exact

@clerk/electron

npm i @clerk/electron@0.0.15-snapshot.v20260716135136 --save-exact

@clerk/electron-passkeys

npm i @clerk/electron-passkeys@0.0.4-snapshot.v20260716135136 --save-exact

@clerk/eslint-plugin

npm i @clerk/eslint-plugin@0.2.1-snapshot.v20260716135136 --save-exact

@clerk/expo

npm i @clerk/expo@3.7.7-snapshot.v20260716135136 --save-exact

@clerk/expo-passkeys

npm i @clerk/expo-passkeys@1.2.6-snapshot.v20260716135136 --save-exact

@clerk/express

npm i @clerk/express@2.1.43-snapshot.v20260716135136 --save-exact

@clerk/fastify

npm i @clerk/fastify@3.1.53-snapshot.v20260716135136 --save-exact

@clerk/headless

npm i @clerk/headless@0.0.13-snapshot.v20260716135136 --save-exact

@clerk/hono

npm i @clerk/hono@0.1.53-snapshot.v20260716135136 --save-exact

@clerk/localizations

npm i @clerk/localizations@4.13.5-snapshot.v20260716135136 --save-exact

@clerk/msw

npm i @clerk/msw@0.0.49-snapshot.v20260716135136 --save-exact

@clerk/nextjs

npm i @clerk/nextjs@7.5.20-snapshot.v20260716135136 --save-exact

@clerk/nuxt

npm i @clerk/nuxt@2.6.19-snapshot.v20260716135136 --save-exact

@clerk/react

npm i @clerk/react@6.12.5-snapshot.v20260716135136 --save-exact

@clerk/react-router

npm i @clerk/react-router@3.5.12-snapshot.v20260716135136 --save-exact

@clerk/shared

npm i @clerk/shared@4.25.5-snapshot.v20260716135136 --save-exact

@clerk/swingset

npm i @clerk/swingset@0.0.20-snapshot.v20260716135136 --save-exact

@clerk/tanstack-react-start

npm i @clerk/tanstack-react-start@1.4.20-snapshot.v20260716135136 --save-exact

@clerk/testing

npm i @clerk/testing@2.2.10-snapshot.v20260716135136 --save-exact

@clerk/ui

npm i @clerk/ui@1.26.0-snapshot.v20260716135136 --save-exact

@clerk/upgrade

npm i @clerk/upgrade@2.0.5-snapshot.v20260716135136 --save-exact

@clerk/vue

npm i @clerk/vue@2.4.17-snapshot.v20260716135136 --save-exact

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (5)
packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx (1)

31-55: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Memoize the context value to avoid needless consumer re-renders.

orgProfileCtxValue (including a brand-new customPages: [] array) is recreated on every render and passed straight into OrganizationProfileContext.Provider. Any consumer relying on referential identity (e.g. a useEffect/useMemo dependency on customPages or the context object itself) will re-run needlessly on every re-render of this provider.

♻️ Suggested fix
- const orgProfileCtxValue = {- componentName: 'OrganizationProfile' as const,- mode: 'mounted' as const,- routing: 'hash' as const,- path: undefined,- afterLeaveOrganizationUrl,- apiKeysProps,- customPages: [],- };+ const orgProfileCtxValue = useMemo(+ () => ({+ componentName: 'OrganizationProfile' as const,+ mode: 'mounted' as const,+ routing: 'hash' as const,+ path: undefined,+ afterLeaveOrganizationUrl,+ apiKeysProps,+ customPages: [],+ }),+ [afterLeaveOrganizationUrl, apiKeysProps],+ );

As per coding guidelines, **/*.{tsx,jsx} should "Minimize re-renders in React components" and "Use proper useMemo for expensive computations in React components."

🤖 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/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx`
around lines 31 - 55, Memoize orgProfileCtxValue in OrganizationProfileProvider
so its object identity remains stable across renders, including the customPages
array. Use React’s memoization hook with dependencies covering
afterLeaveOrganizationUrl and apiKeysProps, while keeping the existing context
fields and provider behavior unchanged.

Source: Coding guidelines

packages/ui/src/experimental/index.ts (1)

10-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace the chained wildcard barrels with deliberate public exports.

The intermediate and published barrels together expose future symbols and collisions through @clerk/ui/experimental.

  • packages/ui/src/experimental/index.ts#L10-L10: explicitly export the supported experimental components from their leaf modules.
  • packages/ui/src/composed/index.ts#L1-L2: remove the intermediate wildcard aggregation or replace it with an explicit internal export list.

As per coding guidelines, “Avoid barrel files (index.ts re-exports) as they can cause circular dependencies.”

🤖 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/ui/src/experimental/index.ts` at line 10, Replace the wildcard
export in packages/ui/src/experimental/index.ts at line 10 with explicit exports
of the supported experimental components from their leaf modules. In
packages/ui/src/composed/index.ts at lines 1-2, remove the wildcard aggregation
or replace it with an explicit internal export list so future symbols and
collisions are not exposed.

Source: Coding guidelines

integration/tests/composed-components.test.ts (1)

31-45: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add an integration fixture without a local 'use client' boundary.

This page becomes a Client Component, so it cannot verify the advertised ability to import and render these exports directly from a React Server Component. Add a minimal server page that imports the experimental components and asserts they render.

As per coding guidelines, include tests for all new features.

🤖 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 `@integration/tests/composed-components.test.ts` around lines 31 - 45, Update
the composedUserProfilePage fixture to remove the local 'use client' directive
and keep it as a minimal React Server Component that imports and renders the
experimental UserProfile exports. Ensure the integration test asserts successful
rendering from this server page, covering the direct server-component import
path for all newly supported components.

Source: Coding guidelines

packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx (1)

18-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add explicit return types to exported components.

  • packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx#L18-L18: annotate the component return type.
  • packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx#L46-L46: annotate the newly exported component return type.
  • packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx#L26-L26: annotate the exported component return type.

As per coding guidelines, exported TypeScript APIs require explicit return types; based on learnings, this repository enforces that for exported functions.

🤖 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/ui/src/elements/ProfileCard/ProfilePagePanel.tsx` at line 18, Add
explicit return type annotations to the exported components ProfilePagePanel,
ConfigureSSO, and ProfileCardPage. Update each component declaration at
packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx:18-18,
packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx:46-46, and
packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx:26-26, using the
appropriate React component return type while preserving their existing
behavior.

Sources: Coding guidelines, Learnings

packages/ui/src/composed/UserProfile/UserProfileProvider.tsx (1)

29-37: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Memoize the context value to avoid re-rendering the whole composed subtree.

userProfileCtxValue is a new object every render, so all descendants consuming UserProfileContext re-render on every UserProfileProvider render regardless of whether any field changed. ProfileProviderShell already memoizes its comparable derived values (router, options), so this is inconsistent with the pattern elsewhere in the layer.

As per coding guidelines, "**/*.{jsx,tsx}": "Use proper useMemo for expensive computations in React components" and "Minimize re-renders in React components."

♻️ Proposed fix
+import { useMemo } from 'react';
...
- const userProfileCtxValue = {- componentName: 'UserProfile' as const,- mode: 'mounted' as const,- routing: 'hash' as const,- path: undefined,- additionalOAuthScopes,- apiKeysProps,- customPages: [],- };+ const userProfileCtxValue = useMemo(+ () => ({+ componentName: 'UserProfile' as const,+ mode: 'mounted' as const,+ routing: 'hash' as const,+ path: undefined,+ additionalOAuthScopes,+ apiKeysProps,+ customPages: [],+ }),+ [additionalOAuthScopes, apiKeysProps],+ );
🤖 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/ui/src/composed/UserProfile/UserProfileProvider.tsx` around lines 29
- 37, Memoize the userProfileCtxValue object in UserProfileProvider with
React.useMemo, using all values included in the context object—especially
additionalOAuthScopes and apiKeysProps—as dependencies; preserve the existing
constant fields and empty customPages value.

Source: Coding guidelines

🤖 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 `@integration/tests/composed-components.test.ts`:
- Around line 127-130: Update the afterAll cleanup blocks around fake users,
organizations, and related temporary entities to use try/finally so each entity
deletion is attempted safely and app.teardown() always runs independently of API
cleanup failures. Preserve the existing cleanup targets and ordering where
possible while ensuring failures in assertions or deletion do not prevent
subsequent cleanup.
In `@packages/ui/src/composed/__tests__/action-animation.test.tsx`:
- Around line 16-26: Replace any-based animation helper types with
Parameters<Element['animate']> call tuples and Keyframe/Keyframe[] types in
findAddAnimationCall and the corresponding helpers in
packages/ui/src/composed/__tests__/action-animation.test.tsx (lines 16-26) and
packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx (lines
28-48). In packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx
(lines 62-68), replace the as any mock result with an Animation-typed fixture or
narrow Partial<Animation> cast.
In `@packages/ui/src/styledSystem/createEmotionCache.ts`:
- Around line 3-4: Update the Emotion insert override in createEmotionCache so
its assigned function inherits cache.insert’s parameter types instead of
declaring an explicit any; keep sheet typed as Emotion’s StyleSheet and remove
the now-unused SerializedStyles import.
---
Nitpick comments:
In `@integration/tests/composed-components.test.ts`:
- Around line 31-45: Update the composedUserProfilePage fixture to remove the
local 'use client' directive and keep it as a minimal React Server Component
that imports and renders the experimental UserProfile exports. Ensure the
integration test asserts successful rendering from this server page, covering
the direct server-component import path for all newly supported components.
In
`@packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx`:
- Around line 31-55: Memoize orgProfileCtxValue in OrganizationProfileProvider
so its object identity remains stable across renders, including the customPages
array. Use React’s memoization hook with dependencies covering
afterLeaveOrganizationUrl and apiKeysProps, while keeping the existing context
fields and provider behavior unchanged.
In `@packages/ui/src/composed/UserProfile/UserProfileProvider.tsx`:
- Around line 29-37: Memoize the userProfileCtxValue object in
UserProfileProvider with React.useMemo, using all values included in the context
object—especially additionalOAuthScopes and apiKeysProps—as dependencies;
preserve the existing constant fields and empty customPages value.
In `@packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx`:
- Line 18: Add explicit return type annotations to the exported components
ProfilePagePanel, ConfigureSSO, and ProfileCardPage. Update each component
declaration at packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx:18-18,
packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx:46-46, and
packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx:26-26, using the
appropriate React component return type while preserving their existing
behavior.
In `@packages/ui/src/experimental/index.ts`:
- Line 10: Replace the wildcard export in packages/ui/src/experimental/index.ts
at line 10 with explicit exports of the supported experimental components from
their leaf modules. In packages/ui/src/composed/index.ts at lines 1-2, remove
the wildcard aggregation or replace it with an explicit internal export list so
future symbols and collisions are not exposed.
🪄 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 Plus

Run ID: 4b6a5164-137f-461f-85b0-6ad847013b23

📥 Commits

Reviewing files that changed from the base of the PR and between 430ae23 and 3464ff9.

⛔ Files ignored due to path filters (1)
  • packages/ui/src/experimental/__tests__/__snapshots__/flat-exports.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (85)
  • .changeset/profile-section-components.md
  • .changeset/shared-moduleManager-registry.md
  • integration/tests/composed-components.test.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/react/src/__tests__/isomorphicClerk.test.ts
  • packages/react/src/isomorphicClerk.ts
  • packages/shared/src/types/clerk.ts
  • packages/ui/package.json
  • packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationBillingPage.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationGeneralPage.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationMembers.tsx
  • packages/ui/src/components/UserProfile/APIKeysPage.tsx
  • packages/ui/src/components/UserProfile/AccountPage.tsx
  • packages/ui/src/components/UserProfile/AccountSections.tsx
  • packages/ui/src/components/UserProfile/BillingPage.tsx
  • packages/ui/src/components/UserProfile/SecurityPage.tsx
  • packages/ui/src/components/UserProfile/SecuritySections.tsx
  • packages/ui/src/components/UserProfile/Web3Form.tsx
  • packages/ui/src/components/UserProfile/__tests__/AccountSections.test.tsx
  • packages/ui/src/components/UserProfile/__tests__/SecuritySections.test.tsx
  • packages/ui/src/components/UserProfile/__tests__/Web3Section.test.tsx
  • packages/ui/src/composed/APIKeysSection.tsx
  • packages/ui/src/composed/BillingSection.tsx
  • packages/ui/src/composed/OrganizationProfile/APIKeys.tsx
  • packages/ui/src/composed/OrganizationProfile/Billing.tsx
  • packages/ui/src/composed/OrganizationProfile/General.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralDeleteOrganization.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralLeaveOrganization.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralOrganizationProfile.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralVerifiedDomains.tsx
  • packages/ui/src/composed/OrganizationProfile/Members.tsx
  • packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx
  • packages/ui/src/composed/OrganizationProfile/Security.tsx
  • packages/ui/src/composed/OrganizationProfile/index.tsx
  • packages/ui/src/composed/PageContext.tsx
  • packages/ui/src/composed/ProfileProviderShell.tsx
  • packages/ui/src/composed/UserProfile/APIKeys.tsx
  • packages/ui/src/composed/UserProfile/Account.tsx
  • packages/ui/src/composed/UserProfile/AccountConnectedAccounts.tsx
  • packages/ui/src/composed/UserProfile/AccountEmails.tsx
  • packages/ui/src/composed/UserProfile/AccountEnterpriseAccounts.tsx
  • packages/ui/src/composed/UserProfile/AccountPhone.tsx
  • packages/ui/src/composed/UserProfile/AccountProfile.tsx
  • packages/ui/src/composed/UserProfile/AccountUsername.tsx
  • packages/ui/src/composed/UserProfile/AccountWeb3.tsx
  • packages/ui/src/composed/UserProfile/Billing.tsx
  • packages/ui/src/composed/UserProfile/Security.tsx
  • packages/ui/src/composed/UserProfile/SecurityActiveDevices.tsx
  • packages/ui/src/composed/UserProfile/SecurityDelete.tsx
  • packages/ui/src/composed/UserProfile/SecurityMfa.tsx
  • packages/ui/src/composed/UserProfile/SecurityPasskeys.tsx
  • packages/ui/src/composed/UserProfile/SecurityPassword.tsx
  • packages/ui/src/composed/UserProfile/UserProfileProvider.tsx
  • packages/ui/src/composed/UserProfile/index.tsx
  • packages/ui/src/composed/__tests__/OrganizationProfile.test.tsx
  • packages/ui/src/composed/__tests__/OrganizationProfileSections.test.tsx
  • packages/ui/src/composed/__tests__/UserProfile.test.tsx
  • packages/ui/src/composed/__tests__/UserProfileSections.test.tsx
  • packages/ui/src/composed/__tests__/action-animation.test.tsx
  • packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx
  • packages/ui/src/composed/__tests__/composed-provider-wiring.test.tsx
  • packages/ui/src/composed/__tests__/hotload-vs-bundle-risks.test.tsx
  • packages/ui/src/composed/__tests__/stub-limitations.test.ts
  • packages/ui/src/composed/__tests__/style-cache-sharing.test.tsx
  • packages/ui/src/composed/createSection.tsx
  • packages/ui/src/composed/index.ts
  • packages/ui/src/composed/stubRouter.ts
  • packages/ui/src/composed/useBillingRouter.ts
  • packages/ui/src/composed/useRequirePage.ts
  • packages/ui/src/customizables/elementDescriptors.ts
  • packages/ui/src/elements/Animated.tsx
  • packages/ui/src/elements/AppearanceOverrides.tsx
  • packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx
  • packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx
  • packages/ui/src/elements/ProfileCard/__tests__/ProfilePagePanel.test.tsx
  • packages/ui/src/elements/ProfileCard/index.ts
  • packages/ui/src/experimental/__tests__/flat-exports.test.ts
  • packages/ui/src/experimental/index.ts
  • packages/ui/src/hooks/useSafeState.ts
  • packages/ui/src/internal/appearance.ts
  • packages/ui/src/internal/styleCacheStore.ts
  • packages/ui/src/styledSystem/StyleCacheProvider.tsx
  • packages/ui/src/styledSystem/createEmotionCache.ts
  • packages/ui/tsdown.config.mts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • clerk/clerk_go(manual)
  • clerk/dashboard(manual)
  • clerk/accounts(manual)
  • clerk/backoffice(manual)
  • clerk/clerk(manual)
  • clerk/clerk-docs(manual)
  • clerk/cloudflare-workers(manual)

Comment threadintegration/tests/composed-components.test.ts
Comment threadpackages/ui/src/composed/__tests__/action-animation.test.tsx Outdated
Comment threadpackages/ui/src/styledSystem/createEmotionCache.ts Outdated
- Remove `any` from createEmotionCache insert override and animation test helpers
- Type animation call tuples via Parameters<Element['animate']>
- Make integration test cleanup failure-safe with try/finally
@alexcarpenteralexcarpenter changed the title feat(ui): composed profile components (release)feat(ui): Expose composed profile componentsJul 22, 2026
@alexcarpenter
alexcarpenter merged commit 01f2c12 into mainJul 24, 2026
55 checks passed
@alexcarpenter
alexcarpenter deleted the carp/profile-release branch July 24, 2026 13:30
Sign up for freeto 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.

2 participants

@alexcarpenter@brkalow
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' feat(ui): Expose composed profile components by alexcarpenter · Pull Request #9144 · clerk/javascript · GitHub
Skip to content

feat(ui): Expose composed profile components - #9144

Merged
alexcarpenter merged 11 commits into
mainfrom
carp/profile-release
Jul 24, 2026
Merged

feat(ui): Expose composed profile components#9144
alexcarpenter merged 11 commits into
mainfrom
carp/profile-release

Conversation

@alexcarpenter

@alexcarpenteralexcarpenter commented Jul 13, 2026

Copy link
Copy Markdown
Member

Ships the experimental composed profile API under @clerk/ui/experimental. Lets developers build the profile UI from flat, individually-mountable panel and section components instead of the monolithic <UserProfile /> / <OrganizationProfile />. Each export is a top-level client reference, so it renders directly in an RSC tree without a consumer 'use client' boundary.

What this exposes

New entrypoint: @clerk/ui/experimental.

UserProfile

  • Provider: UserProfileProvider
  • Panels: UserProfileAccountPanel, UserProfileSecurityPanel, UserProfileBillingPanel, UserProfileAPIKeysPanel
  • Account sections: UserProfileProfileSection, UserProfileUsernameSection, UserProfileEmailSection, UserProfilePhoneSection, UserProfileConnectedAccountsSection, UserProfileEnterpriseAccountsSection, UserProfileWeb3Section
  • Security sections: UserProfilePasswordSection, UserProfilePasskeysSection, UserProfileMfaSection, UserProfileActiveDevicesSection, UserProfileDeleteSection

OrganizationProfile

  • Provider: OrganizationProfileProvider
  • Panels: OrganizationProfileGeneralPanel, OrganizationProfileMembersPanel, OrganizationProfileBillingPanel, OrganizationProfileAPIKeysPanel, OrganizationProfileSecurityPanel
  • Sections: OrganizationProfileProfileSection, OrganizationProfileDomainsSection, OrganizationProfileLeaveSection, OrganizationProfileDeleteSection

Section wrappers render the same underlying components as standard <UserProfile /> / <OrganizationProfile />, so behavior matches; E2E parity coverage added.

Experimental: API may change; gated behind the /experimental entrypoint.

@vercel

vercelBot commented Jul 13, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
clerk-js-sandboxReadyReadyPreview, CommentJul 21, 2026 11:31pm
swingsetReadyReadyPreview, CommentJul 21, 2026 11:31pm

Request Review

@changeset-bot

changeset-botBot commented Jul 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: cd3228b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 23 packages
NameType
@clerk/uiMinor
@clerk/clerk-jsPatch
@clerk/sharedPatch
@clerk/reactPatch
@clerk/astroPatch
@clerk/chrome-extensionPatch
@clerk/swingsetPatch
@clerk/vuePatch
@clerk/electronPatch
@clerk/expoPatch
@clerk/backendPatch
@clerk/expo-passkeysPatch
@clerk/expressPatch
@clerk/fastifyPatch
@clerk/headlessPatch
@clerk/honoPatch
@clerk/localizationsPatch
@clerk/mswPatch
@clerk/nextjsPatch
@clerk/nuxtPatch
@clerk/react-routerPatch
@clerk/tanstack-react-startPatch
@clerk/testingPatch

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

@coderabbitai

coderabbitaiBot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change introduces experimental composable UserProfile and OrganizationProfile exports through @clerk/ui/experimental. It adds providers, panels, sections, routing, runtime module-manager access, shared style-cache handling, profile layout primitives, and conditional rendering logic. It also refactors account and security pages, improves Web3 error handling and animation lifecycle management, and adds unit, Vitest, and Playwright coverage for composed flows and exports.

Estimated code review effort: 5 (Critical) | ~120 minutes

Suggested reviewers:brkalow

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 8.70% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Title check✅ PassedThe title clearly summarizes the main change: exposing composed profile components in the UI package.
Description check✅ PassedThe description matches the changeset by documenting the experimental composed profile API and its exported panels and sections.

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

@pkg-pr-new

pkg-pr-newBot commented Jul 13, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

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

@clerk/backend

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

@clerk/chrome-extension

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

@clerk/clerk-js

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

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@9144

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@9144

@clerk/eslint-plugin

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

@clerk/expo

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

@clerk/expo-google-signin

npm i https://pkg.pr.new/@clerk/expo-google-signin@9144

@clerk/expo-passkeys

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

@clerk/express

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

@clerk/fastify

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

@clerk/hono

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

@clerk/localizations

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

@clerk/nextjs

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

@clerk/nuxt

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

@clerk/react

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

@clerk/react-router

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

@clerk/shared

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

@clerk/tanstack-react-start

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

@clerk/testing

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

@clerk/ui

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

@clerk/upgrade

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

@clerk/vue

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

commit: cd3228b

@github-actions

github-actionsBot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

API Changes Report

Generated by Break Check on 2026-07-21T23:33:34.901Z

Summary

MetricCount
Packages analyzed19
Packages with changes1
🔴 Breaking changes0
🟡 Non-breaking changes1
🟢 Additions1

🤖 This report was reviewed by claude-sonnet-4-6.


@clerk/ui

Current version: 1.25.6
Recommended bump: MINOR → 1.26.0

Subpath ./experimental

🟢 Additions (1)

Added: ./experimental

New subpath export ./experimental (27 exported members)

Subpath ./internal

🟡 Non-breaking Changes (1)

Modified: ElementsConfig
// ... 391 unchanged lines elided ...
profileSectionPrimaryButton: WithOptions<ProfileSectionId>;
profileSectionButtonGroup: WithOptions<ProfileSectionId>;
profilePage: WithOptions<ProfilePageId>;
+ profilePageContent: WithOptions;
formattedPhoneNumber: WithOptions;
formattedPhoneNumberFlag: WithOptions;
formattedPhoneNumberText: WithOptions;
// ... 158 unchanged lines elided ...

Static analyzer: Breaking change in type alias ElementsConfig: Type changed: {button:import("@clerk/ui").~WithOptions<string>;input:import("@clerk/ui").~WithOptions;checkbox:import("@clerk/ui").~W…{button:import("@clerk/ui").~WithOptions<string>;input:import("@clerk/ui").~WithOptions;checkbox:import("@clerk/ui").~W…

🤖 AI review (reclassified as non-breaking) (85%): The elided section grew by exactly one line (475 → 476), indicating a new key was added to ElementsConfig; ElementsConfig is used only as a mapped-type source for the output type Elements, so consumers never construct values of this type directly — adding a new output-only property is non-breaking.


Report generated by Break Check

Last ran on cd3228b.

@alexcarpenter

Copy link
Copy Markdown
MemberAuthor

!snapshot

@github-actions

Copy link
Copy Markdown
Contributor

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

PackageVersion
@clerk/astro3.4.19-snapshot.v20260716135136
@clerk/backend3.11.7-snapshot.v20260716135136
@clerk/chrome-extension3.1.54-snapshot.v20260716135136
@clerk/clerk-js6.25.5-snapshot.v20260716135136
@clerk/electron0.0.15-snapshot.v20260716135136
@clerk/electron-passkeys0.0.4-snapshot.v20260716135136
@clerk/eslint-plugin0.2.1-snapshot.v20260716135136
@clerk/expo3.7.7-snapshot.v20260716135136
@clerk/expo-passkeys1.2.6-snapshot.v20260716135136
@clerk/express2.1.43-snapshot.v20260716135136
@clerk/fastify3.1.53-snapshot.v20260716135136
@clerk/headless0.0.13-snapshot.v20260716135136
@clerk/hono0.1.53-snapshot.v20260716135136
@clerk/localizations4.13.5-snapshot.v20260716135136
@clerk/msw0.0.49-snapshot.v20260716135136
@clerk/nextjs7.5.20-snapshot.v20260716135136
@clerk/nuxt2.6.19-snapshot.v20260716135136
@clerk/react6.12.5-snapshot.v20260716135136
@clerk/react-router3.5.12-snapshot.v20260716135136
@clerk/shared4.25.5-snapshot.v20260716135136
@clerk/swingset0.0.20-snapshot.v20260716135136
@clerk/tanstack-react-start1.4.20-snapshot.v20260716135136
@clerk/testing2.2.10-snapshot.v20260716135136
@clerk/ui1.26.0-snapshot.v20260716135136
@clerk/upgrade2.0.5-snapshot.v20260716135136
@clerk/vue2.4.17-snapshot.v20260716135136

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

npm i @clerk/astro@3.4.19-snapshot.v20260716135136 --save-exact

@clerk/backend

npm i @clerk/backend@3.11.7-snapshot.v20260716135136 --save-exact

@clerk/chrome-extension

npm i @clerk/chrome-extension@3.1.54-snapshot.v20260716135136 --save-exact

@clerk/clerk-js

npm i @clerk/clerk-js@6.25.5-snapshot.v20260716135136 --save-exact

@clerk/electron

npm i @clerk/electron@0.0.15-snapshot.v20260716135136 --save-exact

@clerk/electron-passkeys

npm i @clerk/electron-passkeys@0.0.4-snapshot.v20260716135136 --save-exact

@clerk/eslint-plugin

npm i @clerk/eslint-plugin@0.2.1-snapshot.v20260716135136 --save-exact

@clerk/expo

npm i @clerk/expo@3.7.7-snapshot.v20260716135136 --save-exact

@clerk/expo-passkeys

npm i @clerk/expo-passkeys@1.2.6-snapshot.v20260716135136 --save-exact

@clerk/express

npm i @clerk/express@2.1.43-snapshot.v20260716135136 --save-exact

@clerk/fastify

npm i @clerk/fastify@3.1.53-snapshot.v20260716135136 --save-exact

@clerk/headless

npm i @clerk/headless@0.0.13-snapshot.v20260716135136 --save-exact

@clerk/hono

npm i @clerk/hono@0.1.53-snapshot.v20260716135136 --save-exact

@clerk/localizations

npm i @clerk/localizations@4.13.5-snapshot.v20260716135136 --save-exact

@clerk/msw

npm i @clerk/msw@0.0.49-snapshot.v20260716135136 --save-exact

@clerk/nextjs

npm i @clerk/nextjs@7.5.20-snapshot.v20260716135136 --save-exact

@clerk/nuxt

npm i @clerk/nuxt@2.6.19-snapshot.v20260716135136 --save-exact

@clerk/react

npm i @clerk/react@6.12.5-snapshot.v20260716135136 --save-exact

@clerk/react-router

npm i @clerk/react-router@3.5.12-snapshot.v20260716135136 --save-exact

@clerk/shared

npm i @clerk/shared@4.25.5-snapshot.v20260716135136 --save-exact

@clerk/swingset

npm i @clerk/swingset@0.0.20-snapshot.v20260716135136 --save-exact

@clerk/tanstack-react-start

npm i @clerk/tanstack-react-start@1.4.20-snapshot.v20260716135136 --save-exact

@clerk/testing

npm i @clerk/testing@2.2.10-snapshot.v20260716135136 --save-exact

@clerk/ui

npm i @clerk/ui@1.26.0-snapshot.v20260716135136 --save-exact

@clerk/upgrade

npm i @clerk/upgrade@2.0.5-snapshot.v20260716135136 --save-exact

@clerk/vue

npm i @clerk/vue@2.4.17-snapshot.v20260716135136 --save-exact

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (5)
packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx (1)

31-55: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Memoize the context value to avoid needless consumer re-renders.

orgProfileCtxValue (including a brand-new customPages: [] array) is recreated on every render and passed straight into OrganizationProfileContext.Provider. Any consumer relying on referential identity (e.g. a useEffect/useMemo dependency on customPages or the context object itself) will re-run needlessly on every re-render of this provider.

♻️ Suggested fix
- const orgProfileCtxValue = {- componentName: 'OrganizationProfile' as const,- mode: 'mounted' as const,- routing: 'hash' as const,- path: undefined,- afterLeaveOrganizationUrl,- apiKeysProps,- customPages: [],- };+ const orgProfileCtxValue = useMemo(+ () => ({+ componentName: 'OrganizationProfile' as const,+ mode: 'mounted' as const,+ routing: 'hash' as const,+ path: undefined,+ afterLeaveOrganizationUrl,+ apiKeysProps,+ customPages: [],+ }),+ [afterLeaveOrganizationUrl, apiKeysProps],+ );

As per coding guidelines, **/*.{tsx,jsx} should "Minimize re-renders in React components" and "Use proper useMemo for expensive computations in React components."

🤖 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/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx`
around lines 31 - 55, Memoize orgProfileCtxValue in OrganizationProfileProvider
so its object identity remains stable across renders, including the customPages
array. Use React’s memoization hook with dependencies covering
afterLeaveOrganizationUrl and apiKeysProps, while keeping the existing context
fields and provider behavior unchanged.

Source: Coding guidelines

packages/ui/src/experimental/index.ts (1)

10-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace the chained wildcard barrels with deliberate public exports.

The intermediate and published barrels together expose future symbols and collisions through @clerk/ui/experimental.

  • packages/ui/src/experimental/index.ts#L10-L10: explicitly export the supported experimental components from their leaf modules.
  • packages/ui/src/composed/index.ts#L1-L2: remove the intermediate wildcard aggregation or replace it with an explicit internal export list.

As per coding guidelines, “Avoid barrel files (index.ts re-exports) as they can cause circular dependencies.”

🤖 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/ui/src/experimental/index.ts` at line 10, Replace the wildcard
export in packages/ui/src/experimental/index.ts at line 10 with explicit exports
of the supported experimental components from their leaf modules. In
packages/ui/src/composed/index.ts at lines 1-2, remove the wildcard aggregation
or replace it with an explicit internal export list so future symbols and
collisions are not exposed.

Source: Coding guidelines

integration/tests/composed-components.test.ts (1)

31-45: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add an integration fixture without a local 'use client' boundary.

This page becomes a Client Component, so it cannot verify the advertised ability to import and render these exports directly from a React Server Component. Add a minimal server page that imports the experimental components and asserts they render.

As per coding guidelines, include tests for all new features.

🤖 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 `@integration/tests/composed-components.test.ts` around lines 31 - 45, Update
the composedUserProfilePage fixture to remove the local 'use client' directive
and keep it as a minimal React Server Component that imports and renders the
experimental UserProfile exports. Ensure the integration test asserts successful
rendering from this server page, covering the direct server-component import
path for all newly supported components.

Source: Coding guidelines

packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx (1)

18-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add explicit return types to exported components.

  • packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx#L18-L18: annotate the component return type.
  • packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx#L46-L46: annotate the newly exported component return type.
  • packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx#L26-L26: annotate the exported component return type.

As per coding guidelines, exported TypeScript APIs require explicit return types; based on learnings, this repository enforces that for exported functions.

🤖 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/ui/src/elements/ProfileCard/ProfilePagePanel.tsx` at line 18, Add
explicit return type annotations to the exported components ProfilePagePanel,
ConfigureSSO, and ProfileCardPage. Update each component declaration at
packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx:18-18,
packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx:46-46, and
packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx:26-26, using the
appropriate React component return type while preserving their existing
behavior.

Sources: Coding guidelines, Learnings

packages/ui/src/composed/UserProfile/UserProfileProvider.tsx (1)

29-37: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Memoize the context value to avoid re-rendering the whole composed subtree.

userProfileCtxValue is a new object every render, so all descendants consuming UserProfileContext re-render on every UserProfileProvider render regardless of whether any field changed. ProfileProviderShell already memoizes its comparable derived values (router, options), so this is inconsistent with the pattern elsewhere in the layer.

As per coding guidelines, "**/*.{jsx,tsx}": "Use proper useMemo for expensive computations in React components" and "Minimize re-renders in React components."

♻️ Proposed fix
+import { useMemo } from 'react';
...
- const userProfileCtxValue = {- componentName: 'UserProfile' as const,- mode: 'mounted' as const,- routing: 'hash' as const,- path: undefined,- additionalOAuthScopes,- apiKeysProps,- customPages: [],- };+ const userProfileCtxValue = useMemo(+ () => ({+ componentName: 'UserProfile' as const,+ mode: 'mounted' as const,+ routing: 'hash' as const,+ path: undefined,+ additionalOAuthScopes,+ apiKeysProps,+ customPages: [],+ }),+ [additionalOAuthScopes, apiKeysProps],+ );
🤖 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/ui/src/composed/UserProfile/UserProfileProvider.tsx` around lines 29
- 37, Memoize the userProfileCtxValue object in UserProfileProvider with
React.useMemo, using all values included in the context object—especially
additionalOAuthScopes and apiKeysProps—as dependencies; preserve the existing
constant fields and empty customPages value.

Source: Coding guidelines

🤖 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 `@integration/tests/composed-components.test.ts`:
- Around line 127-130: Update the afterAll cleanup blocks around fake users,
organizations, and related temporary entities to use try/finally so each entity
deletion is attempted safely and app.teardown() always runs independently of API
cleanup failures. Preserve the existing cleanup targets and ordering where
possible while ensuring failures in assertions or deletion do not prevent
subsequent cleanup.
In `@packages/ui/src/composed/__tests__/action-animation.test.tsx`:
- Around line 16-26: Replace any-based animation helper types with
Parameters<Element['animate']> call tuples and Keyframe/Keyframe[] types in
findAddAnimationCall and the corresponding helpers in
packages/ui/src/composed/__tests__/action-animation.test.tsx (lines 16-26) and
packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx (lines
28-48). In packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx
(lines 62-68), replace the as any mock result with an Animation-typed fixture or
narrow Partial<Animation> cast.
In `@packages/ui/src/styledSystem/createEmotionCache.ts`:
- Around line 3-4: Update the Emotion insert override in createEmotionCache so
its assigned function inherits cache.insert’s parameter types instead of
declaring an explicit any; keep sheet typed as Emotion’s StyleSheet and remove
the now-unused SerializedStyles import.
---
Nitpick comments:
In `@integration/tests/composed-components.test.ts`:
- Around line 31-45: Update the composedUserProfilePage fixture to remove the
local 'use client' directive and keep it as a minimal React Server Component
that imports and renders the experimental UserProfile exports. Ensure the
integration test asserts successful rendering from this server page, covering
the direct server-component import path for all newly supported components.
In
`@packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx`:
- Around line 31-55: Memoize orgProfileCtxValue in OrganizationProfileProvider
so its object identity remains stable across renders, including the customPages
array. Use React’s memoization hook with dependencies covering
afterLeaveOrganizationUrl and apiKeysProps, while keeping the existing context
fields and provider behavior unchanged.
In `@packages/ui/src/composed/UserProfile/UserProfileProvider.tsx`:
- Around line 29-37: Memoize the userProfileCtxValue object in
UserProfileProvider with React.useMemo, using all values included in the context
object—especially additionalOAuthScopes and apiKeysProps—as dependencies;
preserve the existing constant fields and empty customPages value.
In `@packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx`:
- Line 18: Add explicit return type annotations to the exported components
ProfilePagePanel, ConfigureSSO, and ProfileCardPage. Update each component
declaration at packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx:18-18,
packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx:46-46, and
packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx:26-26, using the
appropriate React component return type while preserving their existing
behavior.
In `@packages/ui/src/experimental/index.ts`:
- Line 10: Replace the wildcard export in packages/ui/src/experimental/index.ts
at line 10 with explicit exports of the supported experimental components from
their leaf modules. In packages/ui/src/composed/index.ts at lines 1-2, remove
the wildcard aggregation or replace it with an explicit internal export list so
future symbols and collisions are not exposed.
🪄 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 Plus

Run ID: 4b6a5164-137f-461f-85b0-6ad847013b23

📥 Commits

Reviewing files that changed from the base of the PR and between 430ae23 and 3464ff9.

⛔ Files ignored due to path filters (1)
  • packages/ui/src/experimental/__tests__/__snapshots__/flat-exports.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (85)
  • .changeset/profile-section-components.md
  • .changeset/shared-moduleManager-registry.md
  • integration/tests/composed-components.test.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/react/src/__tests__/isomorphicClerk.test.ts
  • packages/react/src/isomorphicClerk.ts
  • packages/shared/src/types/clerk.ts
  • packages/ui/package.json
  • packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationBillingPage.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationGeneralPage.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationMembers.tsx
  • packages/ui/src/components/UserProfile/APIKeysPage.tsx
  • packages/ui/src/components/UserProfile/AccountPage.tsx
  • packages/ui/src/components/UserProfile/AccountSections.tsx
  • packages/ui/src/components/UserProfile/BillingPage.tsx
  • packages/ui/src/components/UserProfile/SecurityPage.tsx
  • packages/ui/src/components/UserProfile/SecuritySections.tsx
  • packages/ui/src/components/UserProfile/Web3Form.tsx
  • packages/ui/src/components/UserProfile/__tests__/AccountSections.test.tsx
  • packages/ui/src/components/UserProfile/__tests__/SecuritySections.test.tsx
  • packages/ui/src/components/UserProfile/__tests__/Web3Section.test.tsx
  • packages/ui/src/composed/APIKeysSection.tsx
  • packages/ui/src/composed/BillingSection.tsx
  • packages/ui/src/composed/OrganizationProfile/APIKeys.tsx
  • packages/ui/src/composed/OrganizationProfile/Billing.tsx
  • packages/ui/src/composed/OrganizationProfile/General.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralDeleteOrganization.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralLeaveOrganization.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralOrganizationProfile.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralVerifiedDomains.tsx
  • packages/ui/src/composed/OrganizationProfile/Members.tsx
  • packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx
  • packages/ui/src/composed/OrganizationProfile/Security.tsx
  • packages/ui/src/composed/OrganizationProfile/index.tsx
  • packages/ui/src/composed/PageContext.tsx
  • packages/ui/src/composed/ProfileProviderShell.tsx
  • packages/ui/src/composed/UserProfile/APIKeys.tsx
  • packages/ui/src/composed/UserProfile/Account.tsx
  • packages/ui/src/composed/UserProfile/AccountConnectedAccounts.tsx
  • packages/ui/src/composed/UserProfile/AccountEmails.tsx
  • packages/ui/src/composed/UserProfile/AccountEnterpriseAccounts.tsx
  • packages/ui/src/composed/UserProfile/AccountPhone.tsx
  • packages/ui/src/composed/UserProfile/AccountProfile.tsx
  • packages/ui/src/composed/UserProfile/AccountUsername.tsx
  • packages/ui/src/composed/UserProfile/AccountWeb3.tsx
  • packages/ui/src/composed/UserProfile/Billing.tsx
  • packages/ui/src/composed/UserProfile/Security.tsx
  • packages/ui/src/composed/UserProfile/SecurityActiveDevices.tsx
  • packages/ui/src/composed/UserProfile/SecurityDelete.tsx
  • packages/ui/src/composed/UserProfile/SecurityMfa.tsx
  • packages/ui/src/composed/UserProfile/SecurityPasskeys.tsx
  • packages/ui/src/composed/UserProfile/SecurityPassword.tsx
  • packages/ui/src/composed/UserProfile/UserProfileProvider.tsx
  • packages/ui/src/composed/UserProfile/index.tsx
  • packages/ui/src/composed/__tests__/OrganizationProfile.test.tsx
  • packages/ui/src/composed/__tests__/OrganizationProfileSections.test.tsx
  • packages/ui/src/composed/__tests__/UserProfile.test.tsx
  • packages/ui/src/composed/__tests__/UserProfileSections.test.tsx
  • packages/ui/src/composed/__tests__/action-animation.test.tsx
  • packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx
  • packages/ui/src/composed/__tests__/composed-provider-wiring.test.tsx
  • packages/ui/src/composed/__tests__/hotload-vs-bundle-risks.test.tsx
  • packages/ui/src/composed/__tests__/stub-limitations.test.ts
  • packages/ui/src/composed/__tests__/style-cache-sharing.test.tsx
  • packages/ui/src/composed/createSection.tsx
  • packages/ui/src/composed/index.ts
  • packages/ui/src/composed/stubRouter.ts
  • packages/ui/src/composed/useBillingRouter.ts
  • packages/ui/src/composed/useRequirePage.ts
  • packages/ui/src/customizables/elementDescriptors.ts
  • packages/ui/src/elements/Animated.tsx
  • packages/ui/src/elements/AppearanceOverrides.tsx
  • packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx
  • packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx
  • packages/ui/src/elements/ProfileCard/__tests__/ProfilePagePanel.test.tsx
  • packages/ui/src/elements/ProfileCard/index.ts
  • packages/ui/src/experimental/__tests__/flat-exports.test.ts
  • packages/ui/src/experimental/index.ts
  • packages/ui/src/hooks/useSafeState.ts
  • packages/ui/src/internal/appearance.ts
  • packages/ui/src/internal/styleCacheStore.ts
  • packages/ui/src/styledSystem/StyleCacheProvider.tsx
  • packages/ui/src/styledSystem/createEmotionCache.ts
  • packages/ui/tsdown.config.mts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • clerk/clerk_go(manual)
  • clerk/dashboard(manual)
  • clerk/accounts(manual)
  • clerk/backoffice(manual)
  • clerk/clerk(manual)
  • clerk/clerk-docs(manual)
  • clerk/cloudflare-workers(manual)

Comment threadintegration/tests/composed-components.test.ts
Comment threadpackages/ui/src/composed/__tests__/action-animation.test.tsx Outdated
Comment threadpackages/ui/src/styledSystem/createEmotionCache.ts Outdated
- Remove `any` from createEmotionCache insert override and animation test helpers
- Type animation call tuples via Parameters<Element['animate']>
- Make integration test cleanup failure-safe with try/finally
@alexcarpenteralexcarpenter changed the title feat(ui): composed profile components (release)feat(ui): Expose composed profile componentsJul 22, 2026
@alexcarpenter
alexcarpenter merged commit 01f2c12 into mainJul 24, 2026
55 checks passed
@alexcarpenter
alexcarpenter deleted the carp/profile-release branch July 24, 2026 13:30
Sign up for freeto 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.

2 participants

@alexcarpenter@brkalow
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(ui): Expose composed profile components by alexcarpenter · Pull Request #9144 · clerk/javascript · GitHub
Skip to content

feat(ui): Expose composed profile components - #9144

Merged
alexcarpenter merged 11 commits into
mainfrom
carp/profile-release
Jul 24, 2026
Merged

feat(ui): Expose composed profile components#9144
alexcarpenter merged 11 commits into
mainfrom
carp/profile-release

Conversation

@alexcarpenter

@alexcarpenteralexcarpenter commented Jul 13, 2026

Copy link
Copy Markdown
Member

Ships the experimental composed profile API under @clerk/ui/experimental. Lets developers build the profile UI from flat, individually-mountable panel and section components instead of the monolithic <UserProfile /> / <OrganizationProfile />. Each export is a top-level client reference, so it renders directly in an RSC tree without a consumer 'use client' boundary.

What this exposes

New entrypoint: @clerk/ui/experimental.

UserProfile

  • Provider: UserProfileProvider
  • Panels: UserProfileAccountPanel, UserProfileSecurityPanel, UserProfileBillingPanel, UserProfileAPIKeysPanel
  • Account sections: UserProfileProfileSection, UserProfileUsernameSection, UserProfileEmailSection, UserProfilePhoneSection, UserProfileConnectedAccountsSection, UserProfileEnterpriseAccountsSection, UserProfileWeb3Section
  • Security sections: UserProfilePasswordSection, UserProfilePasskeysSection, UserProfileMfaSection, UserProfileActiveDevicesSection, UserProfileDeleteSection

OrganizationProfile

  • Provider: OrganizationProfileProvider
  • Panels: OrganizationProfileGeneralPanel, OrganizationProfileMembersPanel, OrganizationProfileBillingPanel, OrganizationProfileAPIKeysPanel, OrganizationProfileSecurityPanel
  • Sections: OrganizationProfileProfileSection, OrganizationProfileDomainsSection, OrganizationProfileLeaveSection, OrganizationProfileDeleteSection

Section wrappers render the same underlying components as standard <UserProfile /> / <OrganizationProfile />, so behavior matches; E2E parity coverage added.

Experimental: API may change; gated behind the /experimental entrypoint.

@vercel

vercelBot commented Jul 13, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
clerk-js-sandboxReadyReadyPreview, CommentJul 21, 2026 11:31pm
swingsetReadyReadyPreview, CommentJul 21, 2026 11:31pm

Request Review

@changeset-bot

changeset-botBot commented Jul 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: cd3228b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 23 packages
NameType
@clerk/uiMinor
@clerk/clerk-jsPatch
@clerk/sharedPatch
@clerk/reactPatch
@clerk/astroPatch
@clerk/chrome-extensionPatch
@clerk/swingsetPatch
@clerk/vuePatch
@clerk/electronPatch
@clerk/expoPatch
@clerk/backendPatch
@clerk/expo-passkeysPatch
@clerk/expressPatch
@clerk/fastifyPatch
@clerk/headlessPatch
@clerk/honoPatch
@clerk/localizationsPatch
@clerk/mswPatch
@clerk/nextjsPatch
@clerk/nuxtPatch
@clerk/react-routerPatch
@clerk/tanstack-react-startPatch
@clerk/testingPatch

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

@coderabbitai

coderabbitaiBot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change introduces experimental composable UserProfile and OrganizationProfile exports through @clerk/ui/experimental. It adds providers, panels, sections, routing, runtime module-manager access, shared style-cache handling, profile layout primitives, and conditional rendering logic. It also refactors account and security pages, improves Web3 error handling and animation lifecycle management, and adds unit, Vitest, and Playwright coverage for composed flows and exports.

Estimated code review effort: 5 (Critical) | ~120 minutes

Suggested reviewers:brkalow

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 8.70% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Title check✅ PassedThe title clearly summarizes the main change: exposing composed profile components in the UI package.
Description check✅ PassedThe description matches the changeset by documenting the experimental composed profile API and its exported panels and sections.

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

@pkg-pr-new

pkg-pr-newBot commented Jul 13, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

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

@clerk/backend

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

@clerk/chrome-extension

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

@clerk/clerk-js

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

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@9144

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@9144

@clerk/eslint-plugin

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

@clerk/expo

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

@clerk/expo-google-signin

npm i https://pkg.pr.new/@clerk/expo-google-signin@9144

@clerk/expo-passkeys

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

@clerk/express

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

@clerk/fastify

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

@clerk/hono

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

@clerk/localizations

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

@clerk/nextjs

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

@clerk/nuxt

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

@clerk/react

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

@clerk/react-router

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

@clerk/shared

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

@clerk/tanstack-react-start

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

@clerk/testing

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

@clerk/ui

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

@clerk/upgrade

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

@clerk/vue

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

commit: cd3228b

@github-actions

github-actionsBot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

API Changes Report

Generated by Break Check on 2026-07-21T23:33:34.901Z

Summary

MetricCount
Packages analyzed19
Packages with changes1
🔴 Breaking changes0
🟡 Non-breaking changes1
🟢 Additions1

🤖 This report was reviewed by claude-sonnet-4-6.


@clerk/ui

Current version: 1.25.6
Recommended bump: MINOR → 1.26.0

Subpath ./experimental

🟢 Additions (1)

Added: ./experimental

New subpath export ./experimental (27 exported members)

Subpath ./internal

🟡 Non-breaking Changes (1)

Modified: ElementsConfig
// ... 391 unchanged lines elided ...
profileSectionPrimaryButton: WithOptions<ProfileSectionId>;
profileSectionButtonGroup: WithOptions<ProfileSectionId>;
profilePage: WithOptions<ProfilePageId>;
+ profilePageContent: WithOptions;
formattedPhoneNumber: WithOptions;
formattedPhoneNumberFlag: WithOptions;
formattedPhoneNumberText: WithOptions;
// ... 158 unchanged lines elided ...

Static analyzer: Breaking change in type alias ElementsConfig: Type changed: {button:import("@clerk/ui").~WithOptions<string>;input:import("@clerk/ui").~WithOptions;checkbox:import("@clerk/ui").~W…{button:import("@clerk/ui").~WithOptions<string>;input:import("@clerk/ui").~WithOptions;checkbox:import("@clerk/ui").~W…

🤖 AI review (reclassified as non-breaking) (85%): The elided section grew by exactly one line (475 → 476), indicating a new key was added to ElementsConfig; ElementsConfig is used only as a mapped-type source for the output type Elements, so consumers never construct values of this type directly — adding a new output-only property is non-breaking.


Report generated by Break Check

Last ran on cd3228b.

@alexcarpenter

Copy link
Copy Markdown
MemberAuthor

!snapshot

@github-actions

Copy link
Copy Markdown
Contributor

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

PackageVersion
@clerk/astro3.4.19-snapshot.v20260716135136
@clerk/backend3.11.7-snapshot.v20260716135136
@clerk/chrome-extension3.1.54-snapshot.v20260716135136
@clerk/clerk-js6.25.5-snapshot.v20260716135136
@clerk/electron0.0.15-snapshot.v20260716135136
@clerk/electron-passkeys0.0.4-snapshot.v20260716135136
@clerk/eslint-plugin0.2.1-snapshot.v20260716135136
@clerk/expo3.7.7-snapshot.v20260716135136
@clerk/expo-passkeys1.2.6-snapshot.v20260716135136
@clerk/express2.1.43-snapshot.v20260716135136
@clerk/fastify3.1.53-snapshot.v20260716135136
@clerk/headless0.0.13-snapshot.v20260716135136
@clerk/hono0.1.53-snapshot.v20260716135136
@clerk/localizations4.13.5-snapshot.v20260716135136
@clerk/msw0.0.49-snapshot.v20260716135136
@clerk/nextjs7.5.20-snapshot.v20260716135136
@clerk/nuxt2.6.19-snapshot.v20260716135136
@clerk/react6.12.5-snapshot.v20260716135136
@clerk/react-router3.5.12-snapshot.v20260716135136
@clerk/shared4.25.5-snapshot.v20260716135136
@clerk/swingset0.0.20-snapshot.v20260716135136
@clerk/tanstack-react-start1.4.20-snapshot.v20260716135136
@clerk/testing2.2.10-snapshot.v20260716135136
@clerk/ui1.26.0-snapshot.v20260716135136
@clerk/upgrade2.0.5-snapshot.v20260716135136
@clerk/vue2.4.17-snapshot.v20260716135136

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

npm i @clerk/astro@3.4.19-snapshot.v20260716135136 --save-exact

@clerk/backend

npm i @clerk/backend@3.11.7-snapshot.v20260716135136 --save-exact

@clerk/chrome-extension

npm i @clerk/chrome-extension@3.1.54-snapshot.v20260716135136 --save-exact

@clerk/clerk-js

npm i @clerk/clerk-js@6.25.5-snapshot.v20260716135136 --save-exact

@clerk/electron

npm i @clerk/electron@0.0.15-snapshot.v20260716135136 --save-exact

@clerk/electron-passkeys

npm i @clerk/electron-passkeys@0.0.4-snapshot.v20260716135136 --save-exact

@clerk/eslint-plugin

npm i @clerk/eslint-plugin@0.2.1-snapshot.v20260716135136 --save-exact

@clerk/expo

npm i @clerk/expo@3.7.7-snapshot.v20260716135136 --save-exact

@clerk/expo-passkeys

npm i @clerk/expo-passkeys@1.2.6-snapshot.v20260716135136 --save-exact

@clerk/express

npm i @clerk/express@2.1.43-snapshot.v20260716135136 --save-exact

@clerk/fastify

npm i @clerk/fastify@3.1.53-snapshot.v20260716135136 --save-exact

@clerk/headless

npm i @clerk/headless@0.0.13-snapshot.v20260716135136 --save-exact

@clerk/hono

npm i @clerk/hono@0.1.53-snapshot.v20260716135136 --save-exact

@clerk/localizations

npm i @clerk/localizations@4.13.5-snapshot.v20260716135136 --save-exact

@clerk/msw

npm i @clerk/msw@0.0.49-snapshot.v20260716135136 --save-exact

@clerk/nextjs

npm i @clerk/nextjs@7.5.20-snapshot.v20260716135136 --save-exact

@clerk/nuxt

npm i @clerk/nuxt@2.6.19-snapshot.v20260716135136 --save-exact

@clerk/react

npm i @clerk/react@6.12.5-snapshot.v20260716135136 --save-exact

@clerk/react-router

npm i @clerk/react-router@3.5.12-snapshot.v20260716135136 --save-exact

@clerk/shared

npm i @clerk/shared@4.25.5-snapshot.v20260716135136 --save-exact

@clerk/swingset

npm i @clerk/swingset@0.0.20-snapshot.v20260716135136 --save-exact

@clerk/tanstack-react-start

npm i @clerk/tanstack-react-start@1.4.20-snapshot.v20260716135136 --save-exact

@clerk/testing

npm i @clerk/testing@2.2.10-snapshot.v20260716135136 --save-exact

@clerk/ui

npm i @clerk/ui@1.26.0-snapshot.v20260716135136 --save-exact

@clerk/upgrade

npm i @clerk/upgrade@2.0.5-snapshot.v20260716135136 --save-exact

@clerk/vue

npm i @clerk/vue@2.4.17-snapshot.v20260716135136 --save-exact

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (5)
packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx (1)

31-55: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Memoize the context value to avoid needless consumer re-renders.

orgProfileCtxValue (including a brand-new customPages: [] array) is recreated on every render and passed straight into OrganizationProfileContext.Provider. Any consumer relying on referential identity (e.g. a useEffect/useMemo dependency on customPages or the context object itself) will re-run needlessly on every re-render of this provider.

♻️ Suggested fix
- const orgProfileCtxValue = {- componentName: 'OrganizationProfile' as const,- mode: 'mounted' as const,- routing: 'hash' as const,- path: undefined,- afterLeaveOrganizationUrl,- apiKeysProps,- customPages: [],- };+ const orgProfileCtxValue = useMemo(+ () => ({+ componentName: 'OrganizationProfile' as const,+ mode: 'mounted' as const,+ routing: 'hash' as const,+ path: undefined,+ afterLeaveOrganizationUrl,+ apiKeysProps,+ customPages: [],+ }),+ [afterLeaveOrganizationUrl, apiKeysProps],+ );

As per coding guidelines, **/*.{tsx,jsx} should "Minimize re-renders in React components" and "Use proper useMemo for expensive computations in React components."

🤖 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/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx`
around lines 31 - 55, Memoize orgProfileCtxValue in OrganizationProfileProvider
so its object identity remains stable across renders, including the customPages
array. Use React’s memoization hook with dependencies covering
afterLeaveOrganizationUrl and apiKeysProps, while keeping the existing context
fields and provider behavior unchanged.

Source: Coding guidelines

packages/ui/src/experimental/index.ts (1)

10-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace the chained wildcard barrels with deliberate public exports.

The intermediate and published barrels together expose future symbols and collisions through @clerk/ui/experimental.

  • packages/ui/src/experimental/index.ts#L10-L10: explicitly export the supported experimental components from their leaf modules.
  • packages/ui/src/composed/index.ts#L1-L2: remove the intermediate wildcard aggregation or replace it with an explicit internal export list.

As per coding guidelines, “Avoid barrel files (index.ts re-exports) as they can cause circular dependencies.”

🤖 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/ui/src/experimental/index.ts` at line 10, Replace the wildcard
export in packages/ui/src/experimental/index.ts at line 10 with explicit exports
of the supported experimental components from their leaf modules. In
packages/ui/src/composed/index.ts at lines 1-2, remove the wildcard aggregation
or replace it with an explicit internal export list so future symbols and
collisions are not exposed.

Source: Coding guidelines

integration/tests/composed-components.test.ts (1)

31-45: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add an integration fixture without a local 'use client' boundary.

This page becomes a Client Component, so it cannot verify the advertised ability to import and render these exports directly from a React Server Component. Add a minimal server page that imports the experimental components and asserts they render.

As per coding guidelines, include tests for all new features.

🤖 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 `@integration/tests/composed-components.test.ts` around lines 31 - 45, Update
the composedUserProfilePage fixture to remove the local 'use client' directive
and keep it as a minimal React Server Component that imports and renders the
experimental UserProfile exports. Ensure the integration test asserts successful
rendering from this server page, covering the direct server-component import
path for all newly supported components.

Source: Coding guidelines

packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx (1)

18-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add explicit return types to exported components.

  • packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx#L18-L18: annotate the component return type.
  • packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx#L46-L46: annotate the newly exported component return type.
  • packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx#L26-L26: annotate the exported component return type.

As per coding guidelines, exported TypeScript APIs require explicit return types; based on learnings, this repository enforces that for exported functions.

🤖 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/ui/src/elements/ProfileCard/ProfilePagePanel.tsx` at line 18, Add
explicit return type annotations to the exported components ProfilePagePanel,
ConfigureSSO, and ProfileCardPage. Update each component declaration at
packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx:18-18,
packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx:46-46, and
packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx:26-26, using the
appropriate React component return type while preserving their existing
behavior.

Sources: Coding guidelines, Learnings

packages/ui/src/composed/UserProfile/UserProfileProvider.tsx (1)

29-37: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Memoize the context value to avoid re-rendering the whole composed subtree.

userProfileCtxValue is a new object every render, so all descendants consuming UserProfileContext re-render on every UserProfileProvider render regardless of whether any field changed. ProfileProviderShell already memoizes its comparable derived values (router, options), so this is inconsistent with the pattern elsewhere in the layer.

As per coding guidelines, "**/*.{jsx,tsx}": "Use proper useMemo for expensive computations in React components" and "Minimize re-renders in React components."

♻️ Proposed fix
+import { useMemo } from 'react';
...
- const userProfileCtxValue = {- componentName: 'UserProfile' as const,- mode: 'mounted' as const,- routing: 'hash' as const,- path: undefined,- additionalOAuthScopes,- apiKeysProps,- customPages: [],- };+ const userProfileCtxValue = useMemo(+ () => ({+ componentName: 'UserProfile' as const,+ mode: 'mounted' as const,+ routing: 'hash' as const,+ path: undefined,+ additionalOAuthScopes,+ apiKeysProps,+ customPages: [],+ }),+ [additionalOAuthScopes, apiKeysProps],+ );
🤖 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/ui/src/composed/UserProfile/UserProfileProvider.tsx` around lines 29
- 37, Memoize the userProfileCtxValue object in UserProfileProvider with
React.useMemo, using all values included in the context object—especially
additionalOAuthScopes and apiKeysProps—as dependencies; preserve the existing
constant fields and empty customPages value.

Source: Coding guidelines

🤖 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 `@integration/tests/composed-components.test.ts`:
- Around line 127-130: Update the afterAll cleanup blocks around fake users,
organizations, and related temporary entities to use try/finally so each entity
deletion is attempted safely and app.teardown() always runs independently of API
cleanup failures. Preserve the existing cleanup targets and ordering where
possible while ensuring failures in assertions or deletion do not prevent
subsequent cleanup.
In `@packages/ui/src/composed/__tests__/action-animation.test.tsx`:
- Around line 16-26: Replace any-based animation helper types with
Parameters<Element['animate']> call tuples and Keyframe/Keyframe[] types in
findAddAnimationCall and the corresponding helpers in
packages/ui/src/composed/__tests__/action-animation.test.tsx (lines 16-26) and
packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx (lines
28-48). In packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx
(lines 62-68), replace the as any mock result with an Animation-typed fixture or
narrow Partial<Animation> cast.
In `@packages/ui/src/styledSystem/createEmotionCache.ts`:
- Around line 3-4: Update the Emotion insert override in createEmotionCache so
its assigned function inherits cache.insert’s parameter types instead of
declaring an explicit any; keep sheet typed as Emotion’s StyleSheet and remove
the now-unused SerializedStyles import.
---
Nitpick comments:
In `@integration/tests/composed-components.test.ts`:
- Around line 31-45: Update the composedUserProfilePage fixture to remove the
local 'use client' directive and keep it as a minimal React Server Component
that imports and renders the experimental UserProfile exports. Ensure the
integration test asserts successful rendering from this server page, covering
the direct server-component import path for all newly supported components.
In
`@packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx`:
- Around line 31-55: Memoize orgProfileCtxValue in OrganizationProfileProvider
so its object identity remains stable across renders, including the customPages
array. Use React’s memoization hook with dependencies covering
afterLeaveOrganizationUrl and apiKeysProps, while keeping the existing context
fields and provider behavior unchanged.
In `@packages/ui/src/composed/UserProfile/UserProfileProvider.tsx`:
- Around line 29-37: Memoize the userProfileCtxValue object in
UserProfileProvider with React.useMemo, using all values included in the context
object—especially additionalOAuthScopes and apiKeysProps—as dependencies;
preserve the existing constant fields and empty customPages value.
In `@packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx`:
- Line 18: Add explicit return type annotations to the exported components
ProfilePagePanel, ConfigureSSO, and ProfileCardPage. Update each component
declaration at packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx:18-18,
packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx:46-46, and
packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx:26-26, using the
appropriate React component return type while preserving their existing
behavior.
In `@packages/ui/src/experimental/index.ts`:
- Line 10: Replace the wildcard export in packages/ui/src/experimental/index.ts
at line 10 with explicit exports of the supported experimental components from
their leaf modules. In packages/ui/src/composed/index.ts at lines 1-2, remove
the wildcard aggregation or replace it with an explicit internal export list so
future symbols and collisions are not exposed.
🪄 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 Plus

Run ID: 4b6a5164-137f-461f-85b0-6ad847013b23

📥 Commits

Reviewing files that changed from the base of the PR and between 430ae23 and 3464ff9.

⛔ Files ignored due to path filters (1)
  • packages/ui/src/experimental/__tests__/__snapshots__/flat-exports.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (85)
  • .changeset/profile-section-components.md
  • .changeset/shared-moduleManager-registry.md
  • integration/tests/composed-components.test.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/react/src/__tests__/isomorphicClerk.test.ts
  • packages/react/src/isomorphicClerk.ts
  • packages/shared/src/types/clerk.ts
  • packages/ui/package.json
  • packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationBillingPage.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationGeneralPage.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationMembers.tsx
  • packages/ui/src/components/UserProfile/APIKeysPage.tsx
  • packages/ui/src/components/UserProfile/AccountPage.tsx
  • packages/ui/src/components/UserProfile/AccountSections.tsx
  • packages/ui/src/components/UserProfile/BillingPage.tsx
  • packages/ui/src/components/UserProfile/SecurityPage.tsx
  • packages/ui/src/components/UserProfile/SecuritySections.tsx
  • packages/ui/src/components/UserProfile/Web3Form.tsx
  • packages/ui/src/components/UserProfile/__tests__/AccountSections.test.tsx
  • packages/ui/src/components/UserProfile/__tests__/SecuritySections.test.tsx
  • packages/ui/src/components/UserProfile/__tests__/Web3Section.test.tsx
  • packages/ui/src/composed/APIKeysSection.tsx
  • packages/ui/src/composed/BillingSection.tsx
  • packages/ui/src/composed/OrganizationProfile/APIKeys.tsx
  • packages/ui/src/composed/OrganizationProfile/Billing.tsx
  • packages/ui/src/composed/OrganizationProfile/General.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralDeleteOrganization.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralLeaveOrganization.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralOrganizationProfile.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralVerifiedDomains.tsx
  • packages/ui/src/composed/OrganizationProfile/Members.tsx
  • packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx
  • packages/ui/src/composed/OrganizationProfile/Security.tsx
  • packages/ui/src/composed/OrganizationProfile/index.tsx
  • packages/ui/src/composed/PageContext.tsx
  • packages/ui/src/composed/ProfileProviderShell.tsx
  • packages/ui/src/composed/UserProfile/APIKeys.tsx
  • packages/ui/src/composed/UserProfile/Account.tsx
  • packages/ui/src/composed/UserProfile/AccountConnectedAccounts.tsx
  • packages/ui/src/composed/UserProfile/AccountEmails.tsx
  • packages/ui/src/composed/UserProfile/AccountEnterpriseAccounts.tsx
  • packages/ui/src/composed/UserProfile/AccountPhone.tsx
  • packages/ui/src/composed/UserProfile/AccountProfile.tsx
  • packages/ui/src/composed/UserProfile/AccountUsername.tsx
  • packages/ui/src/composed/UserProfile/AccountWeb3.tsx
  • packages/ui/src/composed/UserProfile/Billing.tsx
  • packages/ui/src/composed/UserProfile/Security.tsx
  • packages/ui/src/composed/UserProfile/SecurityActiveDevices.tsx
  • packages/ui/src/composed/UserProfile/SecurityDelete.tsx
  • packages/ui/src/composed/UserProfile/SecurityMfa.tsx
  • packages/ui/src/composed/UserProfile/SecurityPasskeys.tsx
  • packages/ui/src/composed/UserProfile/SecurityPassword.tsx
  • packages/ui/src/composed/UserProfile/UserProfileProvider.tsx
  • packages/ui/src/composed/UserProfile/index.tsx
  • packages/ui/src/composed/__tests__/OrganizationProfile.test.tsx
  • packages/ui/src/composed/__tests__/OrganizationProfileSections.test.tsx
  • packages/ui/src/composed/__tests__/UserProfile.test.tsx
  • packages/ui/src/composed/__tests__/UserProfileSections.test.tsx
  • packages/ui/src/composed/__tests__/action-animation.test.tsx
  • packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx
  • packages/ui/src/composed/__tests__/composed-provider-wiring.test.tsx
  • packages/ui/src/composed/__tests__/hotload-vs-bundle-risks.test.tsx
  • packages/ui/src/composed/__tests__/stub-limitations.test.ts
  • packages/ui/src/composed/__tests__/style-cache-sharing.test.tsx
  • packages/ui/src/composed/createSection.tsx
  • packages/ui/src/composed/index.ts
  • packages/ui/src/composed/stubRouter.ts
  • packages/ui/src/composed/useBillingRouter.ts
  • packages/ui/src/composed/useRequirePage.ts
  • packages/ui/src/customizables/elementDescriptors.ts
  • packages/ui/src/elements/Animated.tsx
  • packages/ui/src/elements/AppearanceOverrides.tsx
  • packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx
  • packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx
  • packages/ui/src/elements/ProfileCard/__tests__/ProfilePagePanel.test.tsx
  • packages/ui/src/elements/ProfileCard/index.ts
  • packages/ui/src/experimental/__tests__/flat-exports.test.ts
  • packages/ui/src/experimental/index.ts
  • packages/ui/src/hooks/useSafeState.ts
  • packages/ui/src/internal/appearance.ts
  • packages/ui/src/internal/styleCacheStore.ts
  • packages/ui/src/styledSystem/StyleCacheProvider.tsx
  • packages/ui/src/styledSystem/createEmotionCache.ts
  • packages/ui/tsdown.config.mts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • clerk/clerk_go(manual)
  • clerk/dashboard(manual)
  • clerk/accounts(manual)
  • clerk/backoffice(manual)
  • clerk/clerk(manual)
  • clerk/clerk-docs(manual)
  • clerk/cloudflare-workers(manual)

Comment threadintegration/tests/composed-components.test.ts
Comment threadpackages/ui/src/composed/__tests__/action-animation.test.tsx Outdated
Comment threadpackages/ui/src/styledSystem/createEmotionCache.ts Outdated
- Remove `any` from createEmotionCache insert override and animation test helpers
- Type animation call tuples via Parameters<Element['animate']>
- Make integration test cleanup failure-safe with try/finally
@alexcarpenteralexcarpenter changed the title feat(ui): composed profile components (release)feat(ui): Expose composed profile componentsJul 22, 2026
@alexcarpenter
alexcarpenter merged commit 01f2c12 into mainJul 24, 2026
55 checks passed
@alexcarpenter
alexcarpenter deleted the carp/profile-release branch July 24, 2026 13:30
Sign up for freeto 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.

2 participants

@alexcarpenter@brkalow
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(ui): Expose composed profile components by alexcarpenter · Pull Request #9144 · clerk/javascript · GitHub
Skip to content

feat(ui): Expose composed profile components - #9144

Merged
alexcarpenter merged 11 commits into
mainfrom
carp/profile-release
Jul 24, 2026
Merged

feat(ui): Expose composed profile components#9144
alexcarpenter merged 11 commits into
mainfrom
carp/profile-release

Conversation

@alexcarpenter

@alexcarpenteralexcarpenter commented Jul 13, 2026

Copy link
Copy Markdown
Member

Ships the experimental composed profile API under @clerk/ui/experimental. Lets developers build the profile UI from flat, individually-mountable panel and section components instead of the monolithic <UserProfile /> / <OrganizationProfile />. Each export is a top-level client reference, so it renders directly in an RSC tree without a consumer 'use client' boundary.

What this exposes

New entrypoint: @clerk/ui/experimental.

UserProfile

  • Provider: UserProfileProvider
  • Panels: UserProfileAccountPanel, UserProfileSecurityPanel, UserProfileBillingPanel, UserProfileAPIKeysPanel
  • Account sections: UserProfileProfileSection, UserProfileUsernameSection, UserProfileEmailSection, UserProfilePhoneSection, UserProfileConnectedAccountsSection, UserProfileEnterpriseAccountsSection, UserProfileWeb3Section
  • Security sections: UserProfilePasswordSection, UserProfilePasskeysSection, UserProfileMfaSection, UserProfileActiveDevicesSection, UserProfileDeleteSection

OrganizationProfile

  • Provider: OrganizationProfileProvider
  • Panels: OrganizationProfileGeneralPanel, OrganizationProfileMembersPanel, OrganizationProfileBillingPanel, OrganizationProfileAPIKeysPanel, OrganizationProfileSecurityPanel
  • Sections: OrganizationProfileProfileSection, OrganizationProfileDomainsSection, OrganizationProfileLeaveSection, OrganizationProfileDeleteSection

Section wrappers render the same underlying components as standard <UserProfile /> / <OrganizationProfile />, so behavior matches; E2E parity coverage added.

Experimental: API may change; gated behind the /experimental entrypoint.

@vercel

vercelBot commented Jul 13, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
clerk-js-sandboxReadyReadyPreview, CommentJul 21, 2026 11:31pm
swingsetReadyReadyPreview, CommentJul 21, 2026 11:31pm

Request Review

@changeset-bot

changeset-botBot commented Jul 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: cd3228b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 23 packages
NameType
@clerk/uiMinor
@clerk/clerk-jsPatch
@clerk/sharedPatch
@clerk/reactPatch
@clerk/astroPatch
@clerk/chrome-extensionPatch
@clerk/swingsetPatch
@clerk/vuePatch
@clerk/electronPatch
@clerk/expoPatch
@clerk/backendPatch
@clerk/expo-passkeysPatch
@clerk/expressPatch
@clerk/fastifyPatch
@clerk/headlessPatch
@clerk/honoPatch
@clerk/localizationsPatch
@clerk/mswPatch
@clerk/nextjsPatch
@clerk/nuxtPatch
@clerk/react-routerPatch
@clerk/tanstack-react-startPatch
@clerk/testingPatch

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

@coderabbitai

coderabbitaiBot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change introduces experimental composable UserProfile and OrganizationProfile exports through @clerk/ui/experimental. It adds providers, panels, sections, routing, runtime module-manager access, shared style-cache handling, profile layout primitives, and conditional rendering logic. It also refactors account and security pages, improves Web3 error handling and animation lifecycle management, and adds unit, Vitest, and Playwright coverage for composed flows and exports.

Estimated code review effort: 5 (Critical) | ~120 minutes

Suggested reviewers:brkalow

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 8.70% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Title check✅ PassedThe title clearly summarizes the main change: exposing composed profile components in the UI package.
Description check✅ PassedThe description matches the changeset by documenting the experimental composed profile API and its exported panels and sections.

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

@pkg-pr-new

pkg-pr-newBot commented Jul 13, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

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

@clerk/backend

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

@clerk/chrome-extension

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

@clerk/clerk-js

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

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@9144

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@9144

@clerk/eslint-plugin

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

@clerk/expo

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

@clerk/expo-google-signin

npm i https://pkg.pr.new/@clerk/expo-google-signin@9144

@clerk/expo-passkeys

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

@clerk/express

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

@clerk/fastify

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

@clerk/hono

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

@clerk/localizations

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

@clerk/nextjs

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

@clerk/nuxt

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

@clerk/react

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

@clerk/react-router

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

@clerk/shared

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

@clerk/tanstack-react-start

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

@clerk/testing

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

@clerk/ui

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

@clerk/upgrade

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

@clerk/vue

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

commit: cd3228b

@github-actions

github-actionsBot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

API Changes Report

Generated by Break Check on 2026-07-21T23:33:34.901Z

Summary

MetricCount
Packages analyzed19
Packages with changes1
🔴 Breaking changes0
🟡 Non-breaking changes1
🟢 Additions1

🤖 This report was reviewed by claude-sonnet-4-6.


@clerk/ui

Current version: 1.25.6
Recommended bump: MINOR → 1.26.0

Subpath ./experimental

🟢 Additions (1)

Added: ./experimental

New subpath export ./experimental (27 exported members)

Subpath ./internal

🟡 Non-breaking Changes (1)

Modified: ElementsConfig
// ... 391 unchanged lines elided ...
profileSectionPrimaryButton: WithOptions<ProfileSectionId>;
profileSectionButtonGroup: WithOptions<ProfileSectionId>;
profilePage: WithOptions<ProfilePageId>;
+ profilePageContent: WithOptions;
formattedPhoneNumber: WithOptions;
formattedPhoneNumberFlag: WithOptions;
formattedPhoneNumberText: WithOptions;
// ... 158 unchanged lines elided ...

Static analyzer: Breaking change in type alias ElementsConfig: Type changed: {button:import("@clerk/ui").~WithOptions<string>;input:import("@clerk/ui").~WithOptions;checkbox:import("@clerk/ui").~W…{button:import("@clerk/ui").~WithOptions<string>;input:import("@clerk/ui").~WithOptions;checkbox:import("@clerk/ui").~W…

🤖 AI review (reclassified as non-breaking) (85%): The elided section grew by exactly one line (475 → 476), indicating a new key was added to ElementsConfig; ElementsConfig is used only as a mapped-type source for the output type Elements, so consumers never construct values of this type directly — adding a new output-only property is non-breaking.


Report generated by Break Check

Last ran on cd3228b.

@alexcarpenter

Copy link
Copy Markdown
MemberAuthor

!snapshot

@github-actions

Copy link
Copy Markdown
Contributor

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

PackageVersion
@clerk/astro3.4.19-snapshot.v20260716135136
@clerk/backend3.11.7-snapshot.v20260716135136
@clerk/chrome-extension3.1.54-snapshot.v20260716135136
@clerk/clerk-js6.25.5-snapshot.v20260716135136
@clerk/electron0.0.15-snapshot.v20260716135136
@clerk/electron-passkeys0.0.4-snapshot.v20260716135136
@clerk/eslint-plugin0.2.1-snapshot.v20260716135136
@clerk/expo3.7.7-snapshot.v20260716135136
@clerk/expo-passkeys1.2.6-snapshot.v20260716135136
@clerk/express2.1.43-snapshot.v20260716135136
@clerk/fastify3.1.53-snapshot.v20260716135136
@clerk/headless0.0.13-snapshot.v20260716135136
@clerk/hono0.1.53-snapshot.v20260716135136
@clerk/localizations4.13.5-snapshot.v20260716135136
@clerk/msw0.0.49-snapshot.v20260716135136
@clerk/nextjs7.5.20-snapshot.v20260716135136
@clerk/nuxt2.6.19-snapshot.v20260716135136
@clerk/react6.12.5-snapshot.v20260716135136
@clerk/react-router3.5.12-snapshot.v20260716135136
@clerk/shared4.25.5-snapshot.v20260716135136
@clerk/swingset0.0.20-snapshot.v20260716135136
@clerk/tanstack-react-start1.4.20-snapshot.v20260716135136
@clerk/testing2.2.10-snapshot.v20260716135136
@clerk/ui1.26.0-snapshot.v20260716135136
@clerk/upgrade2.0.5-snapshot.v20260716135136
@clerk/vue2.4.17-snapshot.v20260716135136

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

npm i @clerk/astro@3.4.19-snapshot.v20260716135136 --save-exact

@clerk/backend

npm i @clerk/backend@3.11.7-snapshot.v20260716135136 --save-exact

@clerk/chrome-extension

npm i @clerk/chrome-extension@3.1.54-snapshot.v20260716135136 --save-exact

@clerk/clerk-js

npm i @clerk/clerk-js@6.25.5-snapshot.v20260716135136 --save-exact

@clerk/electron

npm i @clerk/electron@0.0.15-snapshot.v20260716135136 --save-exact

@clerk/electron-passkeys

npm i @clerk/electron-passkeys@0.0.4-snapshot.v20260716135136 --save-exact

@clerk/eslint-plugin

npm i @clerk/eslint-plugin@0.2.1-snapshot.v20260716135136 --save-exact

@clerk/expo

npm i @clerk/expo@3.7.7-snapshot.v20260716135136 --save-exact

@clerk/expo-passkeys

npm i @clerk/expo-passkeys@1.2.6-snapshot.v20260716135136 --save-exact

@clerk/express

npm i @clerk/express@2.1.43-snapshot.v20260716135136 --save-exact

@clerk/fastify

npm i @clerk/fastify@3.1.53-snapshot.v20260716135136 --save-exact

@clerk/headless

npm i @clerk/headless@0.0.13-snapshot.v20260716135136 --save-exact

@clerk/hono

npm i @clerk/hono@0.1.53-snapshot.v20260716135136 --save-exact

@clerk/localizations

npm i @clerk/localizations@4.13.5-snapshot.v20260716135136 --save-exact

@clerk/msw

npm i @clerk/msw@0.0.49-snapshot.v20260716135136 --save-exact

@clerk/nextjs

npm i @clerk/nextjs@7.5.20-snapshot.v20260716135136 --save-exact

@clerk/nuxt

npm i @clerk/nuxt@2.6.19-snapshot.v20260716135136 --save-exact

@clerk/react

npm i @clerk/react@6.12.5-snapshot.v20260716135136 --save-exact

@clerk/react-router

npm i @clerk/react-router@3.5.12-snapshot.v20260716135136 --save-exact

@clerk/shared

npm i @clerk/shared@4.25.5-snapshot.v20260716135136 --save-exact

@clerk/swingset

npm i @clerk/swingset@0.0.20-snapshot.v20260716135136 --save-exact

@clerk/tanstack-react-start

npm i @clerk/tanstack-react-start@1.4.20-snapshot.v20260716135136 --save-exact

@clerk/testing

npm i @clerk/testing@2.2.10-snapshot.v20260716135136 --save-exact

@clerk/ui

npm i @clerk/ui@1.26.0-snapshot.v20260716135136 --save-exact

@clerk/upgrade

npm i @clerk/upgrade@2.0.5-snapshot.v20260716135136 --save-exact

@clerk/vue

npm i @clerk/vue@2.4.17-snapshot.v20260716135136 --save-exact

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (5)
packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx (1)

31-55: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Memoize the context value to avoid needless consumer re-renders.

orgProfileCtxValue (including a brand-new customPages: [] array) is recreated on every render and passed straight into OrganizationProfileContext.Provider. Any consumer relying on referential identity (e.g. a useEffect/useMemo dependency on customPages or the context object itself) will re-run needlessly on every re-render of this provider.

♻️ Suggested fix
- const orgProfileCtxValue = {- componentName: 'OrganizationProfile' as const,- mode: 'mounted' as const,- routing: 'hash' as const,- path: undefined,- afterLeaveOrganizationUrl,- apiKeysProps,- customPages: [],- };+ const orgProfileCtxValue = useMemo(+ () => ({+ componentName: 'OrganizationProfile' as const,+ mode: 'mounted' as const,+ routing: 'hash' as const,+ path: undefined,+ afterLeaveOrganizationUrl,+ apiKeysProps,+ customPages: [],+ }),+ [afterLeaveOrganizationUrl, apiKeysProps],+ );

As per coding guidelines, **/*.{tsx,jsx} should "Minimize re-renders in React components" and "Use proper useMemo for expensive computations in React components."

🤖 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/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx`
around lines 31 - 55, Memoize orgProfileCtxValue in OrganizationProfileProvider
so its object identity remains stable across renders, including the customPages
array. Use React’s memoization hook with dependencies covering
afterLeaveOrganizationUrl and apiKeysProps, while keeping the existing context
fields and provider behavior unchanged.

Source: Coding guidelines

packages/ui/src/experimental/index.ts (1)

10-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace the chained wildcard barrels with deliberate public exports.

The intermediate and published barrels together expose future symbols and collisions through @clerk/ui/experimental.

  • packages/ui/src/experimental/index.ts#L10-L10: explicitly export the supported experimental components from their leaf modules.
  • packages/ui/src/composed/index.ts#L1-L2: remove the intermediate wildcard aggregation or replace it with an explicit internal export list.

As per coding guidelines, “Avoid barrel files (index.ts re-exports) as they can cause circular dependencies.”

🤖 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/ui/src/experimental/index.ts` at line 10, Replace the wildcard
export in packages/ui/src/experimental/index.ts at line 10 with explicit exports
of the supported experimental components from their leaf modules. In
packages/ui/src/composed/index.ts at lines 1-2, remove the wildcard aggregation
or replace it with an explicit internal export list so future symbols and
collisions are not exposed.

Source: Coding guidelines

integration/tests/composed-components.test.ts (1)

31-45: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add an integration fixture without a local 'use client' boundary.

This page becomes a Client Component, so it cannot verify the advertised ability to import and render these exports directly from a React Server Component. Add a minimal server page that imports the experimental components and asserts they render.

As per coding guidelines, include tests for all new features.

🤖 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 `@integration/tests/composed-components.test.ts` around lines 31 - 45, Update
the composedUserProfilePage fixture to remove the local 'use client' directive
and keep it as a minimal React Server Component that imports and renders the
experimental UserProfile exports. Ensure the integration test asserts successful
rendering from this server page, covering the direct server-component import
path for all newly supported components.

Source: Coding guidelines

packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx (1)

18-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add explicit return types to exported components.

  • packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx#L18-L18: annotate the component return type.
  • packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx#L46-L46: annotate the newly exported component return type.
  • packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx#L26-L26: annotate the exported component return type.

As per coding guidelines, exported TypeScript APIs require explicit return types; based on learnings, this repository enforces that for exported functions.

🤖 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/ui/src/elements/ProfileCard/ProfilePagePanel.tsx` at line 18, Add
explicit return type annotations to the exported components ProfilePagePanel,
ConfigureSSO, and ProfileCardPage. Update each component declaration at
packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx:18-18,
packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx:46-46, and
packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx:26-26, using the
appropriate React component return type while preserving their existing
behavior.

Sources: Coding guidelines, Learnings

packages/ui/src/composed/UserProfile/UserProfileProvider.tsx (1)

29-37: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Memoize the context value to avoid re-rendering the whole composed subtree.

userProfileCtxValue is a new object every render, so all descendants consuming UserProfileContext re-render on every UserProfileProvider render regardless of whether any field changed. ProfileProviderShell already memoizes its comparable derived values (router, options), so this is inconsistent with the pattern elsewhere in the layer.

As per coding guidelines, "**/*.{jsx,tsx}": "Use proper useMemo for expensive computations in React components" and "Minimize re-renders in React components."

♻️ Proposed fix
+import { useMemo } from 'react';
...
- const userProfileCtxValue = {- componentName: 'UserProfile' as const,- mode: 'mounted' as const,- routing: 'hash' as const,- path: undefined,- additionalOAuthScopes,- apiKeysProps,- customPages: [],- };+ const userProfileCtxValue = useMemo(+ () => ({+ componentName: 'UserProfile' as const,+ mode: 'mounted' as const,+ routing: 'hash' as const,+ path: undefined,+ additionalOAuthScopes,+ apiKeysProps,+ customPages: [],+ }),+ [additionalOAuthScopes, apiKeysProps],+ );
🤖 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/ui/src/composed/UserProfile/UserProfileProvider.tsx` around lines 29
- 37, Memoize the userProfileCtxValue object in UserProfileProvider with
React.useMemo, using all values included in the context object—especially
additionalOAuthScopes and apiKeysProps—as dependencies; preserve the existing
constant fields and empty customPages value.

Source: Coding guidelines

🤖 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 `@integration/tests/composed-components.test.ts`:
- Around line 127-130: Update the afterAll cleanup blocks around fake users,
organizations, and related temporary entities to use try/finally so each entity
deletion is attempted safely and app.teardown() always runs independently of API
cleanup failures. Preserve the existing cleanup targets and ordering where
possible while ensuring failures in assertions or deletion do not prevent
subsequent cleanup.
In `@packages/ui/src/composed/__tests__/action-animation.test.tsx`:
- Around line 16-26: Replace any-based animation helper types with
Parameters<Element['animate']> call tuples and Keyframe/Keyframe[] types in
findAddAnimationCall and the corresponding helpers in
packages/ui/src/composed/__tests__/action-animation.test.tsx (lines 16-26) and
packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx (lines
28-48). In packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx
(lines 62-68), replace the as any mock result with an Animation-typed fixture or
narrow Partial<Animation> cast.
In `@packages/ui/src/styledSystem/createEmotionCache.ts`:
- Around line 3-4: Update the Emotion insert override in createEmotionCache so
its assigned function inherits cache.insert’s parameter types instead of
declaring an explicit any; keep sheet typed as Emotion’s StyleSheet and remove
the now-unused SerializedStyles import.
---
Nitpick comments:
In `@integration/tests/composed-components.test.ts`:
- Around line 31-45: Update the composedUserProfilePage fixture to remove the
local 'use client' directive and keep it as a minimal React Server Component
that imports and renders the experimental UserProfile exports. Ensure the
integration test asserts successful rendering from this server page, covering
the direct server-component import path for all newly supported components.
In
`@packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx`:
- Around line 31-55: Memoize orgProfileCtxValue in OrganizationProfileProvider
so its object identity remains stable across renders, including the customPages
array. Use React’s memoization hook with dependencies covering
afterLeaveOrganizationUrl and apiKeysProps, while keeping the existing context
fields and provider behavior unchanged.
In `@packages/ui/src/composed/UserProfile/UserProfileProvider.tsx`:
- Around line 29-37: Memoize the userProfileCtxValue object in
UserProfileProvider with React.useMemo, using all values included in the context
object—especially additionalOAuthScopes and apiKeysProps—as dependencies;
preserve the existing constant fields and empty customPages value.
In `@packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx`:
- Line 18: Add explicit return type annotations to the exported components
ProfilePagePanel, ConfigureSSO, and ProfileCardPage. Update each component
declaration at packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx:18-18,
packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx:46-46, and
packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx:26-26, using the
appropriate React component return type while preserving their existing
behavior.
In `@packages/ui/src/experimental/index.ts`:
- Line 10: Replace the wildcard export in packages/ui/src/experimental/index.ts
at line 10 with explicit exports of the supported experimental components from
their leaf modules. In packages/ui/src/composed/index.ts at lines 1-2, remove
the wildcard aggregation or replace it with an explicit internal export list so
future symbols and collisions are not exposed.
🪄 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 Plus

Run ID: 4b6a5164-137f-461f-85b0-6ad847013b23

📥 Commits

Reviewing files that changed from the base of the PR and between 430ae23 and 3464ff9.

⛔ Files ignored due to path filters (1)
  • packages/ui/src/experimental/__tests__/__snapshots__/flat-exports.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (85)
  • .changeset/profile-section-components.md
  • .changeset/shared-moduleManager-registry.md
  • integration/tests/composed-components.test.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/react/src/__tests__/isomorphicClerk.test.ts
  • packages/react/src/isomorphicClerk.ts
  • packages/shared/src/types/clerk.ts
  • packages/ui/package.json
  • packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationBillingPage.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationGeneralPage.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationMembers.tsx
  • packages/ui/src/components/UserProfile/APIKeysPage.tsx
  • packages/ui/src/components/UserProfile/AccountPage.tsx
  • packages/ui/src/components/UserProfile/AccountSections.tsx
  • packages/ui/src/components/UserProfile/BillingPage.tsx
  • packages/ui/src/components/UserProfile/SecurityPage.tsx
  • packages/ui/src/components/UserProfile/SecuritySections.tsx
  • packages/ui/src/components/UserProfile/Web3Form.tsx
  • packages/ui/src/components/UserProfile/__tests__/AccountSections.test.tsx
  • packages/ui/src/components/UserProfile/__tests__/SecuritySections.test.tsx
  • packages/ui/src/components/UserProfile/__tests__/Web3Section.test.tsx
  • packages/ui/src/composed/APIKeysSection.tsx
  • packages/ui/src/composed/BillingSection.tsx
  • packages/ui/src/composed/OrganizationProfile/APIKeys.tsx
  • packages/ui/src/composed/OrganizationProfile/Billing.tsx
  • packages/ui/src/composed/OrganizationProfile/General.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralDeleteOrganization.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralLeaveOrganization.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralOrganizationProfile.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralVerifiedDomains.tsx
  • packages/ui/src/composed/OrganizationProfile/Members.tsx
  • packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx
  • packages/ui/src/composed/OrganizationProfile/Security.tsx
  • packages/ui/src/composed/OrganizationProfile/index.tsx
  • packages/ui/src/composed/PageContext.tsx
  • packages/ui/src/composed/ProfileProviderShell.tsx
  • packages/ui/src/composed/UserProfile/APIKeys.tsx
  • packages/ui/src/composed/UserProfile/Account.tsx
  • packages/ui/src/composed/UserProfile/AccountConnectedAccounts.tsx
  • packages/ui/src/composed/UserProfile/AccountEmails.tsx
  • packages/ui/src/composed/UserProfile/AccountEnterpriseAccounts.tsx
  • packages/ui/src/composed/UserProfile/AccountPhone.tsx
  • packages/ui/src/composed/UserProfile/AccountProfile.tsx
  • packages/ui/src/composed/UserProfile/AccountUsername.tsx
  • packages/ui/src/composed/UserProfile/AccountWeb3.tsx
  • packages/ui/src/composed/UserProfile/Billing.tsx
  • packages/ui/src/composed/UserProfile/Security.tsx
  • packages/ui/src/composed/UserProfile/SecurityActiveDevices.tsx
  • packages/ui/src/composed/UserProfile/SecurityDelete.tsx
  • packages/ui/src/composed/UserProfile/SecurityMfa.tsx
  • packages/ui/src/composed/UserProfile/SecurityPasskeys.tsx
  • packages/ui/src/composed/UserProfile/SecurityPassword.tsx
  • packages/ui/src/composed/UserProfile/UserProfileProvider.tsx
  • packages/ui/src/composed/UserProfile/index.tsx
  • packages/ui/src/composed/__tests__/OrganizationProfile.test.tsx
  • packages/ui/src/composed/__tests__/OrganizationProfileSections.test.tsx
  • packages/ui/src/composed/__tests__/UserProfile.test.tsx
  • packages/ui/src/composed/__tests__/UserProfileSections.test.tsx
  • packages/ui/src/composed/__tests__/action-animation.test.tsx
  • packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx
  • packages/ui/src/composed/__tests__/composed-provider-wiring.test.tsx
  • packages/ui/src/composed/__tests__/hotload-vs-bundle-risks.test.tsx
  • packages/ui/src/composed/__tests__/stub-limitations.test.ts
  • packages/ui/src/composed/__tests__/style-cache-sharing.test.tsx
  • packages/ui/src/composed/createSection.tsx
  • packages/ui/src/composed/index.ts
  • packages/ui/src/composed/stubRouter.ts
  • packages/ui/src/composed/useBillingRouter.ts
  • packages/ui/src/composed/useRequirePage.ts
  • packages/ui/src/customizables/elementDescriptors.ts
  • packages/ui/src/elements/Animated.tsx
  • packages/ui/src/elements/AppearanceOverrides.tsx
  • packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx
  • packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx
  • packages/ui/src/elements/ProfileCard/__tests__/ProfilePagePanel.test.tsx
  • packages/ui/src/elements/ProfileCard/index.ts
  • packages/ui/src/experimental/__tests__/flat-exports.test.ts
  • packages/ui/src/experimental/index.ts
  • packages/ui/src/hooks/useSafeState.ts
  • packages/ui/src/internal/appearance.ts
  • packages/ui/src/internal/styleCacheStore.ts
  • packages/ui/src/styledSystem/StyleCacheProvider.tsx
  • packages/ui/src/styledSystem/createEmotionCache.ts
  • packages/ui/tsdown.config.mts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • clerk/clerk_go(manual)
  • clerk/dashboard(manual)
  • clerk/accounts(manual)
  • clerk/backoffice(manual)
  • clerk/clerk(manual)
  • clerk/clerk-docs(manual)
  • clerk/cloudflare-workers(manual)

Comment threadintegration/tests/composed-components.test.ts
Comment threadpackages/ui/src/composed/__tests__/action-animation.test.tsx Outdated
Comment threadpackages/ui/src/styledSystem/createEmotionCache.ts Outdated
- Remove `any` from createEmotionCache insert override and animation test helpers
- Type animation call tuples via Parameters<Element['animate']>
- Make integration test cleanup failure-safe with try/finally
@alexcarpenteralexcarpenter changed the title feat(ui): composed profile components (release)feat(ui): Expose composed profile componentsJul 22, 2026
@alexcarpenter
alexcarpenter merged commit 01f2c12 into mainJul 24, 2026
55 checks passed
@alexcarpenter
alexcarpenter deleted the carp/profile-release branch July 24, 2026 13:30
Sign up for freeto 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.

2 participants

@alexcarpenter@brkalow
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); feat(ui): Expose composed profile components by alexcarpenter · Pull Request #9144 · clerk/javascript · GitHub
Skip to content

feat(ui): Expose composed profile components - #9144

Merged
alexcarpenter merged 11 commits into
mainfrom
carp/profile-release
Jul 24, 2026
Merged

feat(ui): Expose composed profile components#9144
alexcarpenter merged 11 commits into
mainfrom
carp/profile-release

Conversation

@alexcarpenter

@alexcarpenteralexcarpenter commented Jul 13, 2026

Copy link
Copy Markdown
Member

Ships the experimental composed profile API under @clerk/ui/experimental. Lets developers build the profile UI from flat, individually-mountable panel and section components instead of the monolithic <UserProfile /> / <OrganizationProfile />. Each export is a top-level client reference, so it renders directly in an RSC tree without a consumer 'use client' boundary.

What this exposes

New entrypoint: @clerk/ui/experimental.

UserProfile

  • Provider: UserProfileProvider
  • Panels: UserProfileAccountPanel, UserProfileSecurityPanel, UserProfileBillingPanel, UserProfileAPIKeysPanel
  • Account sections: UserProfileProfileSection, UserProfileUsernameSection, UserProfileEmailSection, UserProfilePhoneSection, UserProfileConnectedAccountsSection, UserProfileEnterpriseAccountsSection, UserProfileWeb3Section
  • Security sections: UserProfilePasswordSection, UserProfilePasskeysSection, UserProfileMfaSection, UserProfileActiveDevicesSection, UserProfileDeleteSection

OrganizationProfile

  • Provider: OrganizationProfileProvider
  • Panels: OrganizationProfileGeneralPanel, OrganizationProfileMembersPanel, OrganizationProfileBillingPanel, OrganizationProfileAPIKeysPanel, OrganizationProfileSecurityPanel
  • Sections: OrganizationProfileProfileSection, OrganizationProfileDomainsSection, OrganizationProfileLeaveSection, OrganizationProfileDeleteSection

Section wrappers render the same underlying components as standard <UserProfile /> / <OrganizationProfile />, so behavior matches; E2E parity coverage added.

Experimental: API may change; gated behind the /experimental entrypoint.

@vercel

vercelBot commented Jul 13, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
clerk-js-sandboxReadyReadyPreview, CommentJul 21, 2026 11:31pm
swingsetReadyReadyPreview, CommentJul 21, 2026 11:31pm

Request Review

@changeset-bot

changeset-botBot commented Jul 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: cd3228b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 23 packages
NameType
@clerk/uiMinor
@clerk/clerk-jsPatch
@clerk/sharedPatch
@clerk/reactPatch
@clerk/astroPatch
@clerk/chrome-extensionPatch
@clerk/swingsetPatch
@clerk/vuePatch
@clerk/electronPatch
@clerk/expoPatch
@clerk/backendPatch
@clerk/expo-passkeysPatch
@clerk/expressPatch
@clerk/fastifyPatch
@clerk/headlessPatch
@clerk/honoPatch
@clerk/localizationsPatch
@clerk/mswPatch
@clerk/nextjsPatch
@clerk/nuxtPatch
@clerk/react-routerPatch
@clerk/tanstack-react-startPatch
@clerk/testingPatch

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

@coderabbitai

coderabbitaiBot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change introduces experimental composable UserProfile and OrganizationProfile exports through @clerk/ui/experimental. It adds providers, panels, sections, routing, runtime module-manager access, shared style-cache handling, profile layout primitives, and conditional rendering logic. It also refactors account and security pages, improves Web3 error handling and animation lifecycle management, and adds unit, Vitest, and Playwright coverage for composed flows and exports.

Estimated code review effort: 5 (Critical) | ~120 minutes

Suggested reviewers:brkalow

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 8.70% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
Title check✅ PassedThe title clearly summarizes the main change: exposing composed profile components in the UI package.
Description check✅ PassedThe description matches the changeset by documenting the experimental composed profile API and its exported panels and sections.

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

@pkg-pr-new

pkg-pr-newBot commented Jul 13, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

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

@clerk/backend

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

@clerk/chrome-extension

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

@clerk/clerk-js

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

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@9144

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@9144

@clerk/eslint-plugin

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

@clerk/expo

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

@clerk/expo-google-signin

npm i https://pkg.pr.new/@clerk/expo-google-signin@9144

@clerk/expo-passkeys

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

@clerk/express

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

@clerk/fastify

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

@clerk/hono

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

@clerk/localizations

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

@clerk/nextjs

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

@clerk/nuxt

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

@clerk/react

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

@clerk/react-router

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

@clerk/shared

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

@clerk/tanstack-react-start

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

@clerk/testing

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

@clerk/ui

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

@clerk/upgrade

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

@clerk/vue

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

commit: cd3228b

@github-actions

github-actionsBot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

API Changes Report

Generated by Break Check on 2026-07-21T23:33:34.901Z

Summary

MetricCount
Packages analyzed19
Packages with changes1
🔴 Breaking changes0
🟡 Non-breaking changes1
🟢 Additions1

🤖 This report was reviewed by claude-sonnet-4-6.


@clerk/ui

Current version: 1.25.6
Recommended bump: MINOR → 1.26.0

Subpath ./experimental

🟢 Additions (1)

Added: ./experimental

New subpath export ./experimental (27 exported members)

Subpath ./internal

🟡 Non-breaking Changes (1)

Modified: ElementsConfig
// ... 391 unchanged lines elided ...
profileSectionPrimaryButton: WithOptions<ProfileSectionId>;
profileSectionButtonGroup: WithOptions<ProfileSectionId>;
profilePage: WithOptions<ProfilePageId>;
+ profilePageContent: WithOptions;
formattedPhoneNumber: WithOptions;
formattedPhoneNumberFlag: WithOptions;
formattedPhoneNumberText: WithOptions;
// ... 158 unchanged lines elided ...

Static analyzer: Breaking change in type alias ElementsConfig: Type changed: {button:import("@clerk/ui").~WithOptions<string>;input:import("@clerk/ui").~WithOptions;checkbox:import("@clerk/ui").~W…{button:import("@clerk/ui").~WithOptions<string>;input:import("@clerk/ui").~WithOptions;checkbox:import("@clerk/ui").~W…

🤖 AI review (reclassified as non-breaking) (85%): The elided section grew by exactly one line (475 → 476), indicating a new key was added to ElementsConfig; ElementsConfig is used only as a mapped-type source for the output type Elements, so consumers never construct values of this type directly — adding a new output-only property is non-breaking.


Report generated by Break Check

Last ran on cd3228b.

@alexcarpenter

Copy link
Copy Markdown
MemberAuthor

!snapshot

@github-actions

Copy link
Copy Markdown
Contributor

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

PackageVersion
@clerk/astro3.4.19-snapshot.v20260716135136
@clerk/backend3.11.7-snapshot.v20260716135136
@clerk/chrome-extension3.1.54-snapshot.v20260716135136
@clerk/clerk-js6.25.5-snapshot.v20260716135136
@clerk/electron0.0.15-snapshot.v20260716135136
@clerk/electron-passkeys0.0.4-snapshot.v20260716135136
@clerk/eslint-plugin0.2.1-snapshot.v20260716135136
@clerk/expo3.7.7-snapshot.v20260716135136
@clerk/expo-passkeys1.2.6-snapshot.v20260716135136
@clerk/express2.1.43-snapshot.v20260716135136
@clerk/fastify3.1.53-snapshot.v20260716135136
@clerk/headless0.0.13-snapshot.v20260716135136
@clerk/hono0.1.53-snapshot.v20260716135136
@clerk/localizations4.13.5-snapshot.v20260716135136
@clerk/msw0.0.49-snapshot.v20260716135136
@clerk/nextjs7.5.20-snapshot.v20260716135136
@clerk/nuxt2.6.19-snapshot.v20260716135136
@clerk/react6.12.5-snapshot.v20260716135136
@clerk/react-router3.5.12-snapshot.v20260716135136
@clerk/shared4.25.5-snapshot.v20260716135136
@clerk/swingset0.0.20-snapshot.v20260716135136
@clerk/tanstack-react-start1.4.20-snapshot.v20260716135136
@clerk/testing2.2.10-snapshot.v20260716135136
@clerk/ui1.26.0-snapshot.v20260716135136
@clerk/upgrade2.0.5-snapshot.v20260716135136
@clerk/vue2.4.17-snapshot.v20260716135136

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

npm i @clerk/astro@3.4.19-snapshot.v20260716135136 --save-exact

@clerk/backend

npm i @clerk/backend@3.11.7-snapshot.v20260716135136 --save-exact

@clerk/chrome-extension

npm i @clerk/chrome-extension@3.1.54-snapshot.v20260716135136 --save-exact

@clerk/clerk-js

npm i @clerk/clerk-js@6.25.5-snapshot.v20260716135136 --save-exact

@clerk/electron

npm i @clerk/electron@0.0.15-snapshot.v20260716135136 --save-exact

@clerk/electron-passkeys

npm i @clerk/electron-passkeys@0.0.4-snapshot.v20260716135136 --save-exact

@clerk/eslint-plugin

npm i @clerk/eslint-plugin@0.2.1-snapshot.v20260716135136 --save-exact

@clerk/expo

npm i @clerk/expo@3.7.7-snapshot.v20260716135136 --save-exact

@clerk/expo-passkeys

npm i @clerk/expo-passkeys@1.2.6-snapshot.v20260716135136 --save-exact

@clerk/express

npm i @clerk/express@2.1.43-snapshot.v20260716135136 --save-exact

@clerk/fastify

npm i @clerk/fastify@3.1.53-snapshot.v20260716135136 --save-exact

@clerk/headless

npm i @clerk/headless@0.0.13-snapshot.v20260716135136 --save-exact

@clerk/hono

npm i @clerk/hono@0.1.53-snapshot.v20260716135136 --save-exact

@clerk/localizations

npm i @clerk/localizations@4.13.5-snapshot.v20260716135136 --save-exact

@clerk/msw

npm i @clerk/msw@0.0.49-snapshot.v20260716135136 --save-exact

@clerk/nextjs

npm i @clerk/nextjs@7.5.20-snapshot.v20260716135136 --save-exact

@clerk/nuxt

npm i @clerk/nuxt@2.6.19-snapshot.v20260716135136 --save-exact

@clerk/react

npm i @clerk/react@6.12.5-snapshot.v20260716135136 --save-exact

@clerk/react-router

npm i @clerk/react-router@3.5.12-snapshot.v20260716135136 --save-exact

@clerk/shared

npm i @clerk/shared@4.25.5-snapshot.v20260716135136 --save-exact

@clerk/swingset

npm i @clerk/swingset@0.0.20-snapshot.v20260716135136 --save-exact

@clerk/tanstack-react-start

npm i @clerk/tanstack-react-start@1.4.20-snapshot.v20260716135136 --save-exact

@clerk/testing

npm i @clerk/testing@2.2.10-snapshot.v20260716135136 --save-exact

@clerk/ui

npm i @clerk/ui@1.26.0-snapshot.v20260716135136 --save-exact

@clerk/upgrade

npm i @clerk/upgrade@2.0.5-snapshot.v20260716135136 --save-exact

@clerk/vue

npm i @clerk/vue@2.4.17-snapshot.v20260716135136 --save-exact

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (5)
packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx (1)

31-55: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Memoize the context value to avoid needless consumer re-renders.

orgProfileCtxValue (including a brand-new customPages: [] array) is recreated on every render and passed straight into OrganizationProfileContext.Provider. Any consumer relying on referential identity (e.g. a useEffect/useMemo dependency on customPages or the context object itself) will re-run needlessly on every re-render of this provider.

♻️ Suggested fix
- const orgProfileCtxValue = {- componentName: 'OrganizationProfile' as const,- mode: 'mounted' as const,- routing: 'hash' as const,- path: undefined,- afterLeaveOrganizationUrl,- apiKeysProps,- customPages: [],- };+ const orgProfileCtxValue = useMemo(+ () => ({+ componentName: 'OrganizationProfile' as const,+ mode: 'mounted' as const,+ routing: 'hash' as const,+ path: undefined,+ afterLeaveOrganizationUrl,+ apiKeysProps,+ customPages: [],+ }),+ [afterLeaveOrganizationUrl, apiKeysProps],+ );

As per coding guidelines, **/*.{tsx,jsx} should "Minimize re-renders in React components" and "Use proper useMemo for expensive computations in React components."

🤖 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/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx`
around lines 31 - 55, Memoize orgProfileCtxValue in OrganizationProfileProvider
so its object identity remains stable across renders, including the customPages
array. Use React’s memoization hook with dependencies covering
afterLeaveOrganizationUrl and apiKeysProps, while keeping the existing context
fields and provider behavior unchanged.

Source: Coding guidelines

packages/ui/src/experimental/index.ts (1)

10-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace the chained wildcard barrels with deliberate public exports.

The intermediate and published barrels together expose future symbols and collisions through @clerk/ui/experimental.

  • packages/ui/src/experimental/index.ts#L10-L10: explicitly export the supported experimental components from their leaf modules.
  • packages/ui/src/composed/index.ts#L1-L2: remove the intermediate wildcard aggregation or replace it with an explicit internal export list.

As per coding guidelines, “Avoid barrel files (index.ts re-exports) as they can cause circular dependencies.”

🤖 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/ui/src/experimental/index.ts` at line 10, Replace the wildcard
export in packages/ui/src/experimental/index.ts at line 10 with explicit exports
of the supported experimental components from their leaf modules. In
packages/ui/src/composed/index.ts at lines 1-2, remove the wildcard aggregation
or replace it with an explicit internal export list so future symbols and
collisions are not exposed.

Source: Coding guidelines

integration/tests/composed-components.test.ts (1)

31-45: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add an integration fixture without a local 'use client' boundary.

This page becomes a Client Component, so it cannot verify the advertised ability to import and render these exports directly from a React Server Component. Add a minimal server page that imports the experimental components and asserts they render.

As per coding guidelines, include tests for all new features.

🤖 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 `@integration/tests/composed-components.test.ts` around lines 31 - 45, Update
the composedUserProfilePage fixture to remove the local 'use client' directive
and keep it as a minimal React Server Component that imports and renders the
experimental UserProfile exports. Ensure the integration test asserts successful
rendering from this server page, covering the direct server-component import
path for all newly supported components.

Source: Coding guidelines

packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx (1)

18-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add explicit return types to exported components.

  • packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx#L18-L18: annotate the component return type.
  • packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx#L46-L46: annotate the newly exported component return type.
  • packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx#L26-L26: annotate the exported component return type.

As per coding guidelines, exported TypeScript APIs require explicit return types; based on learnings, this repository enforces that for exported functions.

🤖 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/ui/src/elements/ProfileCard/ProfilePagePanel.tsx` at line 18, Add
explicit return type annotations to the exported components ProfilePagePanel,
ConfigureSSO, and ProfileCardPage. Update each component declaration at
packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx:18-18,
packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx:46-46, and
packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx:26-26, using the
appropriate React component return type while preserving their existing
behavior.

Sources: Coding guidelines, Learnings

packages/ui/src/composed/UserProfile/UserProfileProvider.tsx (1)

29-37: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Memoize the context value to avoid re-rendering the whole composed subtree.

userProfileCtxValue is a new object every render, so all descendants consuming UserProfileContext re-render on every UserProfileProvider render regardless of whether any field changed. ProfileProviderShell already memoizes its comparable derived values (router, options), so this is inconsistent with the pattern elsewhere in the layer.

As per coding guidelines, "**/*.{jsx,tsx}": "Use proper useMemo for expensive computations in React components" and "Minimize re-renders in React components."

♻️ Proposed fix
+import { useMemo } from 'react';
...
- const userProfileCtxValue = {- componentName: 'UserProfile' as const,- mode: 'mounted' as const,- routing: 'hash' as const,- path: undefined,- additionalOAuthScopes,- apiKeysProps,- customPages: [],- };+ const userProfileCtxValue = useMemo(+ () => ({+ componentName: 'UserProfile' as const,+ mode: 'mounted' as const,+ routing: 'hash' as const,+ path: undefined,+ additionalOAuthScopes,+ apiKeysProps,+ customPages: [],+ }),+ [additionalOAuthScopes, apiKeysProps],+ );
🤖 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/ui/src/composed/UserProfile/UserProfileProvider.tsx` around lines 29
- 37, Memoize the userProfileCtxValue object in UserProfileProvider with
React.useMemo, using all values included in the context object—especially
additionalOAuthScopes and apiKeysProps—as dependencies; preserve the existing
constant fields and empty customPages value.

Source: Coding guidelines

🤖 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 `@integration/tests/composed-components.test.ts`:
- Around line 127-130: Update the afterAll cleanup blocks around fake users,
organizations, and related temporary entities to use try/finally so each entity
deletion is attempted safely and app.teardown() always runs independently of API
cleanup failures. Preserve the existing cleanup targets and ordering where
possible while ensuring failures in assertions or deletion do not prevent
subsequent cleanup.
In `@packages/ui/src/composed/__tests__/action-animation.test.tsx`:
- Around line 16-26: Replace any-based animation helper types with
Parameters<Element['animate']> call tuples and Keyframe/Keyframe[] types in
findAddAnimationCall and the corresponding helpers in
packages/ui/src/composed/__tests__/action-animation.test.tsx (lines 16-26) and
packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx (lines
28-48). In packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx
(lines 62-68), replace the as any mock result with an Animation-typed fixture or
narrow Partial<Animation> cast.
In `@packages/ui/src/styledSystem/createEmotionCache.ts`:
- Around line 3-4: Update the Emotion insert override in createEmotionCache so
its assigned function inherits cache.insert’s parameter types instead of
declaring an explicit any; keep sheet typed as Emotion’s StyleSheet and remove
the now-unused SerializedStyles import.
---
Nitpick comments:
In `@integration/tests/composed-components.test.ts`:
- Around line 31-45: Update the composedUserProfilePage fixture to remove the
local 'use client' directive and keep it as a minimal React Server Component
that imports and renders the experimental UserProfile exports. Ensure the
integration test asserts successful rendering from this server page, covering
the direct server-component import path for all newly supported components.
In
`@packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx`:
- Around line 31-55: Memoize orgProfileCtxValue in OrganizationProfileProvider
so its object identity remains stable across renders, including the customPages
array. Use React’s memoization hook with dependencies covering
afterLeaveOrganizationUrl and apiKeysProps, while keeping the existing context
fields and provider behavior unchanged.
In `@packages/ui/src/composed/UserProfile/UserProfileProvider.tsx`:
- Around line 29-37: Memoize the userProfileCtxValue object in
UserProfileProvider with React.useMemo, using all values included in the context
object—especially additionalOAuthScopes and apiKeysProps—as dependencies;
preserve the existing constant fields and empty customPages value.
In `@packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx`:
- Line 18: Add explicit return type annotations to the exported components
ProfilePagePanel, ConfigureSSO, and ProfileCardPage. Update each component
declaration at packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx:18-18,
packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx:46-46, and
packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx:26-26, using the
appropriate React component return type while preserving their existing
behavior.
In `@packages/ui/src/experimental/index.ts`:
- Line 10: Replace the wildcard export in packages/ui/src/experimental/index.ts
at line 10 with explicit exports of the supported experimental components from
their leaf modules. In packages/ui/src/composed/index.ts at lines 1-2, remove
the wildcard aggregation or replace it with an explicit internal export list so
future symbols and collisions are not exposed.
🪄 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 Plus

Run ID: 4b6a5164-137f-461f-85b0-6ad847013b23

📥 Commits

Reviewing files that changed from the base of the PR and between 430ae23 and 3464ff9.

⛔ Files ignored due to path filters (1)
  • packages/ui/src/experimental/__tests__/__snapshots__/flat-exports.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (85)
  • .changeset/profile-section-components.md
  • .changeset/shared-moduleManager-registry.md
  • integration/tests/composed-components.test.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/react/src/__tests__/isomorphicClerk.test.ts
  • packages/react/src/isomorphicClerk.ts
  • packages/shared/src/types/clerk.ts
  • packages/ui/package.json
  • packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationBillingPage.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationGeneralPage.tsx
  • packages/ui/src/components/OrganizationProfile/OrganizationMembers.tsx
  • packages/ui/src/components/UserProfile/APIKeysPage.tsx
  • packages/ui/src/components/UserProfile/AccountPage.tsx
  • packages/ui/src/components/UserProfile/AccountSections.tsx
  • packages/ui/src/components/UserProfile/BillingPage.tsx
  • packages/ui/src/components/UserProfile/SecurityPage.tsx
  • packages/ui/src/components/UserProfile/SecuritySections.tsx
  • packages/ui/src/components/UserProfile/Web3Form.tsx
  • packages/ui/src/components/UserProfile/__tests__/AccountSections.test.tsx
  • packages/ui/src/components/UserProfile/__tests__/SecuritySections.test.tsx
  • packages/ui/src/components/UserProfile/__tests__/Web3Section.test.tsx
  • packages/ui/src/composed/APIKeysSection.tsx
  • packages/ui/src/composed/BillingSection.tsx
  • packages/ui/src/composed/OrganizationProfile/APIKeys.tsx
  • packages/ui/src/composed/OrganizationProfile/Billing.tsx
  • packages/ui/src/composed/OrganizationProfile/General.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralDeleteOrganization.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralLeaveOrganization.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralOrganizationProfile.tsx
  • packages/ui/src/composed/OrganizationProfile/GeneralVerifiedDomains.tsx
  • packages/ui/src/composed/OrganizationProfile/Members.tsx
  • packages/ui/src/composed/OrganizationProfile/OrganizationProfileProvider.tsx
  • packages/ui/src/composed/OrganizationProfile/Security.tsx
  • packages/ui/src/composed/OrganizationProfile/index.tsx
  • packages/ui/src/composed/PageContext.tsx
  • packages/ui/src/composed/ProfileProviderShell.tsx
  • packages/ui/src/composed/UserProfile/APIKeys.tsx
  • packages/ui/src/composed/UserProfile/Account.tsx
  • packages/ui/src/composed/UserProfile/AccountConnectedAccounts.tsx
  • packages/ui/src/composed/UserProfile/AccountEmails.tsx
  • packages/ui/src/composed/UserProfile/AccountEnterpriseAccounts.tsx
  • packages/ui/src/composed/UserProfile/AccountPhone.tsx
  • packages/ui/src/composed/UserProfile/AccountProfile.tsx
  • packages/ui/src/composed/UserProfile/AccountUsername.tsx
  • packages/ui/src/composed/UserProfile/AccountWeb3.tsx
  • packages/ui/src/composed/UserProfile/Billing.tsx
  • packages/ui/src/composed/UserProfile/Security.tsx
  • packages/ui/src/composed/UserProfile/SecurityActiveDevices.tsx
  • packages/ui/src/composed/UserProfile/SecurityDelete.tsx
  • packages/ui/src/composed/UserProfile/SecurityMfa.tsx
  • packages/ui/src/composed/UserProfile/SecurityPasskeys.tsx
  • packages/ui/src/composed/UserProfile/SecurityPassword.tsx
  • packages/ui/src/composed/UserProfile/UserProfileProvider.tsx
  • packages/ui/src/composed/UserProfile/index.tsx
  • packages/ui/src/composed/__tests__/OrganizationProfile.test.tsx
  • packages/ui/src/composed/__tests__/OrganizationProfileSections.test.tsx
  • packages/ui/src/composed/__tests__/UserProfile.test.tsx
  • packages/ui/src/composed/__tests__/UserProfileSections.test.tsx
  • packages/ui/src/composed/__tests__/action-animation.test.tsx
  • packages/ui/src/composed/__tests__/auto-animate-strictmode.test.tsx
  • packages/ui/src/composed/__tests__/composed-provider-wiring.test.tsx
  • packages/ui/src/composed/__tests__/hotload-vs-bundle-risks.test.tsx
  • packages/ui/src/composed/__tests__/stub-limitations.test.ts
  • packages/ui/src/composed/__tests__/style-cache-sharing.test.tsx
  • packages/ui/src/composed/createSection.tsx
  • packages/ui/src/composed/index.ts
  • packages/ui/src/composed/stubRouter.ts
  • packages/ui/src/composed/useBillingRouter.ts
  • packages/ui/src/composed/useRequirePage.ts
  • packages/ui/src/customizables/elementDescriptors.ts
  • packages/ui/src/elements/Animated.tsx
  • packages/ui/src/elements/AppearanceOverrides.tsx
  • packages/ui/src/elements/ProfileCard/ProfileCardPage.tsx
  • packages/ui/src/elements/ProfileCard/ProfilePagePanel.tsx
  • packages/ui/src/elements/ProfileCard/__tests__/ProfilePagePanel.test.tsx
  • packages/ui/src/elements/ProfileCard/index.ts
  • packages/ui/src/experimental/__tests__/flat-exports.test.ts
  • packages/ui/src/experimental/index.ts
  • packages/ui/src/hooks/useSafeState.ts
  • packages/ui/src/internal/appearance.ts
  • packages/ui/src/internal/styleCacheStore.ts
  • packages/ui/src/styledSystem/StyleCacheProvider.tsx
  • packages/ui/src/styledSystem/createEmotionCache.ts
  • packages/ui/tsdown.config.mts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • clerk/clerk_go(manual)
  • clerk/dashboard(manual)
  • clerk/accounts(manual)
  • clerk/backoffice(manual)
  • clerk/clerk(manual)
  • clerk/clerk-docs(manual)
  • clerk/cloudflare-workers(manual)

Comment threadintegration/tests/composed-components.test.ts
Comment threadpackages/ui/src/composed/__tests__/action-animation.test.tsx Outdated
Comment threadpackages/ui/src/styledSystem/createEmotionCache.ts Outdated
- Remove `any` from createEmotionCache insert override and animation test helpers
- Type animation call tuples via Parameters<Element['animate']>
- Make integration test cleanup failure-safe with try/finally
@alexcarpenteralexcarpenter changed the title feat(ui): composed profile components (release)feat(ui): Expose composed profile componentsJul 22, 2026
@alexcarpenter
alexcarpenter merged commit 01f2c12 into mainJul 24, 2026
55 checks passed
@alexcarpenter
alexcarpenter deleted the carp/profile-release branch July 24, 2026 13:30
Sign up for freeto 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.

2 participants

@alexcarpenter@brkalow