feat(ui): Expose profile sub components#8654
Conversation
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
!snapshot |
This comment has been minimized.
This comment has been minimized.
|
!snapshot |
This comment has been minimized.
This comment has been minimized.
|
!snapshot |
This comment has been minimized.
This comment has been minimized.
|
!snapshot |
This comment has been minimized.
This comment has been minimized.
|
!snapshot |
|
Hey @alexcarpenter - the snapshot version command generated the following package versions:
Tip: Use the snippet copy button below to quickly install the required packages. npm i @clerk/astro@3.3.0-snapshot.v20260527161602 --save-exact
npm i @clerk/backend@3.4.12-snapshot.v20260527161602 --save-exact
npm i @clerk/chrome-extension@3.1.29-snapshot.v20260527161602 --save-exact
npm i @clerk/clerk-js@6.12.0-snapshot.v20260527161602 --save-exact
npm i @clerk/dev-cli@0.1.1-snapshot.v20260527161602 --save-exact
npm i @clerk/expo@3.2.15-snapshot.v20260527161602 --save-exact
npm i @clerk/expo-passkeys@1.0.28-snapshot.v20260527161602 --save-exact
npm i @clerk/express@2.1.20-snapshot.v20260527161602 --save-exact
npm i @clerk/fastify@3.1.30-snapshot.v20260527161602 --save-exact
npm i @clerk/hono@0.1.30-snapshot.v20260527161602 --save-exact
npm i @clerk/localizations@4.6.7-snapshot.v20260527161602 --save-exact
npm i @clerk/msw@0.0.28-snapshot.v20260527161602 --save-exact
npm i @clerk/nextjs@7.4.0-snapshot.v20260527161602 --save-exact
npm i @clerk/nuxt@2.5.0-snapshot.v20260527161602 --save-exact
npm i @clerk/react@6.7.0-snapshot.v20260527161602 --save-exact
npm i @clerk/react-router@3.3.0-snapshot.v20260527161602 --save-exact
npm i @clerk/shared@4.13.0-snapshot.v20260527161602 --save-exact
npm i @clerk/tanstack-react-start@1.3.0-snapshot.v20260527161602 --save-exact
npm i @clerk/testing@2.0.32-snapshot.v20260527161602 --save-exact
npm i @clerk/ui@1.13.0-snapshot.v20260527161602 --save-exact
npm i @clerk/upgrade@2.0.3-snapshot.v20260527161602 --save-exact
npm i @clerk/vue@2.3.0-snapshot.v20260527161602 --save-exact |
Add 'use client' to the experimental entrypoint and move the document.querySelector call in StyleCacheProvider from module scope into the useMemo to avoid crashes during server-side rendering. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Annotate every exported composed component with a ReactNode return type so the generated .d.ts files are compatible with both React 18 and React 19 consumers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@clerk/astro
@clerk/backend
@clerk/chrome-extension
@clerk/clerk-js
@clerk/expo
@clerk/expo-passkeys
@clerk/express
@clerk/fastify
@clerk/hono
@clerk/localizations
@clerk/nextjs
@clerk/nuxt
@clerk/react
@clerk/react-router
@clerk/shared
@clerk/tanstack-react-start
@clerk/testing
@clerk/ui
@clerk/upgrade
@clerk/vue
commit: |
|
|
||
| let storedModuleManager: ModuleManager | undefined; | ||
|
|
||
| export function setModuleManager(mm: ModuleManager): void { |
There was a problem hiding this comment.
Module-level store so composed components can access the ModuleManager that ClerkUI receives at mount time. Composed components render outside the normal component tree so they cant inherit it through context from the mount call — ClerkUI.init() calls setModuleManager() and providers read it back via getModuleManager().
| @@ -0,0 +1,30 @@ | |||
| import type { RouteContextValue } from '../router/RouteContext'; | |||
|
|
|||
| export function createComposedRouter(clerkNavigate: (to: string) => Promise<unknown> | void): RouteContextValue { | |||
There was a problem hiding this comment.
Composed components render individual pages, not full routed flows — but many child components still call useRouter() internally. This satisfies that contract with a minimal implementation that delegates to clerk.navigate (or window.location.assign for the static fallback). No actual routing; just enough to prevent crashes from missing context.
|
|
||
| export const StyleCacheProvider = (props: StyleCacheProviderProps) => { | ||
| const cache = useMemo(() => { | ||
| const el = typeof document !== 'undefined' ? document.querySelector('style#cl-style-insertion-point') : null; |
There was a problem hiding this comment.
Moved document.querySelector inside the component body. Top-level call ran at import time which breaks SSR / non-browser environments. Composed components may be imported in SSR-capable frameworks so this needs to be safe.
| const { applyVariants, filterProps } = createVariants(theme => { | ||
| return { | ||
| base: { | ||
| boxSizing: 'border-box', |
There was a problem hiding this comment.
Fixing a sizing issue uncovered where the border rendered outside the size defined causing layout shifts.
| const isMountedRef = React.useRef(true); | ||
|
|
||
| React.useEffect(() => { | ||
| isMountedRef.current = true; |
There was a problem hiding this comment.
Ref initializes as true but under StrictMode the cleanup runs between double-invocation, setting it to false — without this line the second effect never resets it, so setState becomes a permanent no-op.
Summary
Exposes
UserProfileandOrganizationProfileas composable sub-components from@clerk/ui/experimental. Lets consumers render individual profile sections (Account, Security, Members, Billing, etc.) outside the full modal/page flow.Approach
composed/directory — each profile gets a Provider that wires up the required context tree (appearance, environment, module manager, routing, flow metadata) so individual section components render standalone.moduleManagerStore— module-level get/set because composed components mount outside the normal component tree and can't inheritModuleManagervia context fromClerkUI.init().stubRouter— minimalRouteContextimplementation delegating toclerk.navigate. Child components calluseRouter()internally but composed pages don't do real routing.StyleCacheProvider— moveddocument.querySelectorfrom module scope into the component body; import-time access breaks SSR.useSafeState— resetisMountedReftotruein effect body; StrictMode cleanup between double-invocation left it permanentlyfalse.Animated— guard against StrictMode double-mount leaving animation refs stale.@clerk/ui/experimentalwith'use client'directive.API
Sub-components available:
Account,Security,Billing,APIKeys(user);General,Members,Billing,APIKeys,ConfigureSSO(org). Fine-grained wrappers also exported (e.g.AccountProfile,SecurityPasskeys).Test plan
🤖 Generated with Claude Code