diff --git a/.changeset/cuddly-spoons-decide.md b/.changeset/cuddly-spoons-decide.md new file mode 100644 index 00000000000..0a35d2b77f3 --- /dev/null +++ b/.changeset/cuddly-spoons-decide.md @@ -0,0 +1,6 @@ +--- +"@clerk/clerk-js": patch +"@clerk/types": patch +--- + +Add support for opening the `UserProfileModal` and `OrganizationProfileModal` to specific navigation items through the `UserButton` and `OrganizationSwitcher`. diff --git a/packages/clerk-js/src/ui/Components.tsx b/packages/clerk-js/src/ui/Components.tsx index 26eb42ccac8..10ec8472a1c 100644 --- a/packages/clerk-js/src/ui/Components.tsx +++ b/packages/clerk-js/src/ui/Components.tsx @@ -285,8 +285,11 @@ const Components = (props: ComponentsProps) => { flowName={'userProfile'} onClose={() => componentsControls.closeModal('userProfile')} onExternalNavigate={() => componentsControls.closeModal('userProfile')} - startPath={buildVirtualRouterUrl({ base: '/user', path: urlStateParam?.path })} - componentName={'SignUpModal'} + startPath={buildVirtualRouterUrl({ + base: '/user', + path: userProfileModal?.__experimental_startPath || urlStateParam?.path, + })} + componentName={'UserProfileModal'} modalContainerSx={{ alignItems: 'center' }} modalContentSx={t => ({ height: `min(${t.sizes.$176}, calc(100% - ${t.sizes.$12}))`, margin: 0 })} > @@ -302,7 +305,10 @@ const Components = (props: ComponentsProps) => { flowName={'organizationProfile'} onClose={() => componentsControls.closeModal('organizationProfile')} onExternalNavigate={() => componentsControls.closeModal('organizationProfile')} - startPath={buildVirtualRouterUrl({ base: '/organizationProfile', path: urlStateParam?.path })} + startPath={buildVirtualRouterUrl({ + base: '/organizationProfile', + path: organizationProfileModal?.__experimental_startPath || urlStateParam?.path, + })} componentName={'OrganizationProfileModal'} modalContainerSx={{ alignItems: 'center' }} modalContentSx={t => ({ height: `min(${t.sizes.$176}, calc(100% - ${t.sizes.$12}))`, margin: 0 })} diff --git a/packages/clerk-js/src/ui/components/OrganizationSwitcher/OrganizationSwitcherPopover.tsx b/packages/clerk-js/src/ui/components/OrganizationSwitcher/OrganizationSwitcherPopover.tsx index f433fd31da5..aa58e4f0940 100644 --- a/packages/clerk-js/src/ui/components/OrganizationSwitcher/OrganizationSwitcherPopover.tsx +++ b/packages/clerk-js/src/ui/components/OrganizationSwitcher/OrganizationSwitcherPopover.tsx @@ -88,13 +88,15 @@ export const OrganizationSwitcherPopover = React.forwardRef { + const handleItemClick = (__experimental_startPath?: string) => { close(); if (organizationProfileMode === 'navigation') { return navigateOrganizationProfile(); } + return openOrganizationProfile({ ...organizationProfileProps, + ...(__experimental_startPath && { __experimental_startPath }), afterLeaveOrganizationUrl, //@ts-expect-error __unstable_manageBillingUrl, @@ -112,7 +114,7 @@ export const OrganizationSwitcherPopover = React.forwardRef handleItemClick()} trailing={} /> ); @@ -127,7 +129,7 @@ export const OrganizationSwitcherPopover = React.forwardRef handleItemClick()} trailing={} /> ); diff --git a/packages/clerk-js/src/ui/components/UserButton/useMultisessionActions.tsx b/packages/clerk-js/src/ui/components/UserButton/useMultisessionActions.tsx index b9508cdc15d..6dfb5a06d0a 100644 --- a/packages/clerk-js/src/ui/components/UserButton/useMultisessionActions.tsx +++ b/packages/clerk-js/src/ui/components/UserButton/useMultisessionActions.tsx @@ -41,11 +41,27 @@ export const useMultisessionActions = (opts: UseMultisessionActionsParams) => { })(); }); } - openUserProfile(opts.userProfileProps); return opts.actionCompleteCallback?.(); }; + const handleUserProfileActionClicked = (__experimental_startPath?: string) => { + if (opts.userProfileMode === 'navigation') { + return navigate(opts.userProfileUrl || '').finally(() => { + void (async () => { + await sleep(300); + opts.actionCompleteCallback?.(); + })(); + }); + } + openUserProfile({ + ...opts.userProfileProps, + ...(__experimental_startPath && { __experimental_startPath }), + }); + + return opts.actionCompleteCallback?.(); + }; + const handleSignOutAllClicked = () => { return signOut(opts.navigateAfterSignOut); }; @@ -66,6 +82,7 @@ export const useMultisessionActions = (opts: UseMultisessionActionsParams) => { return { handleSignOutSessionClicked, handleManageAccountClicked, + handleUserProfileActionClicked, handleSignOutAllClicked, handleSessionClicked, handleAddAccountClicked, diff --git a/packages/clerk-js/src/ui/hooks/useNavigateToFlowStart.ts b/packages/clerk-js/src/ui/hooks/useNavigateToFlowStart.ts index 79a1b5275b2..fedad013c81 100644 --- a/packages/clerk-js/src/ui/hooks/useNavigateToFlowStart.ts +++ b/packages/clerk-js/src/ui/hooks/useNavigateToFlowStart.ts @@ -3,7 +3,8 @@ import { useRouter } from '../router'; export const useNavigateToFlowStart = () => { const router = useRouter(); const navigateToFlowStart = async () => { - const to = '/' + router.basePath + router.flowStartPath; + const to = router.indexPath; + if (to !== router.currentPath) { return router.navigate(to); } diff --git a/packages/types/src/clerk.ts b/packages/types/src/clerk.ts index 31338858ff9..93c429e29fb 100644 --- a/packages/types/src/clerk.ts +++ b/packages/types/src/clerk.ts @@ -816,6 +816,7 @@ export type UserProfileProps = RoutingOptions & { * Provide custom pages and links to be rendered inside the UserProfile. */ customPages?: CustomPage[]; + __experimental_startPath?: string; }; export type UserProfileModalProps = WithoutRouting; @@ -836,6 +837,7 @@ export type OrganizationProfileProps = RoutingOptions & { * Provide custom pages and links to be rendered inside the OrganizationProfile. */ customPages?: CustomPage[]; + __experimental_startPath?: string; }; export type OrganizationProfileModalProps = WithoutRouting;