Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/cuddly-spoons-decide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@clerk/clerk-js": patch
Comment thread
EmmanouelaPothitou marked this conversation as resolved.
"@clerk/types": patch
---

Add support for opening the `UserProfileModal` and `OrganizationProfileModal` to specific navigation items through the `UserButton` and `OrganizationSwitcher`.
12 changes: 9 additions & 3 deletions packages/clerk-js/src/ui/Components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 })}
>
Expand All @@ -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 })}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,15 @@ export const OrganizationSwitcherPopover = React.forwardRef<HTMLDivElement, Orga
return openCreateOrganization({ afterCreateOrganizationUrl, skipInvitationScreen });
};

const handleManageOrganizationClicked = () => {
const handleItemClick = (__experimental_startPath?: string) => {
close();
if (organizationProfileMode === 'navigation') {
return navigateOrganizationProfile();
}

return openOrganizationProfile({
...organizationProfileProps,
...(__experimental_startPath && { __experimental_startPath }),
afterLeaveOrganizationUrl,
//@ts-expect-error
__unstable_manageBillingUrl,
Expand All @@ -112,7 +114,7 @@ export const OrganizationSwitcherPopover = React.forwardRef<HTMLDivElement, Orga
iconElementDescriptor={descriptors.organizationSwitcherPopoverActionButtonIcon}
iconElementId={descriptors.organizationSwitcherPopoverActionButtonIcon.setId('manageOrganization')}
icon={CogFilled}
onClick={handleManageOrganizationClicked}
onClick={() => handleItemClick()}
Comment thread
nikosdouvlis marked this conversation as resolved.
trailing={<NotificationCountBadgeManageButton />}
/>
);
Expand All @@ -127,7 +129,7 @@ export const OrganizationSwitcherPopover = React.forwardRef<HTMLDivElement, Orga
iconElementId={descriptors.organizationSwitcherPopoverActionButtonIcon.setId('manageOrganization')}
icon={CogFilled}
label={localizationKeys('organizationSwitcher.action__manageOrganization')}
onClick={handleManageOrganizationClicked}
onClick={() => handleItemClick()}
Comment thread
nikosdouvlis marked this conversation as resolved.
trailing={<NotificationCountBadgeManageButton />}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 }),

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.

❓Shouldn't we update the types of UserProfileModalProps and OrgProfileModalProps to include __experimental_startPath ?

});

return opts.actionCompleteCallback?.();
};

const handleSignOutAllClicked = () => {
return signOut(opts.navigateAfterSignOut);
};
Expand All @@ -66,6 +82,7 @@ export const useMultisessionActions = (opts: UseMultisessionActionsParams) => {
return {
handleSignOutSessionClicked,
handleManageAccountClicked,
handleUserProfileActionClicked,
handleSignOutAllClicked,
handleSessionClicked,
handleAddAccountClicked,
Expand Down
3 changes: 2 additions & 1 deletion packages/clerk-js/src/ui/hooks/useNavigateToFlowStart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;

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.

Could you briefly, our discoveries and why this is a "safe" change ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

In the current modal setup, the first element is associated with the '/' path. Previously, clicking the back button in the modal's sidebar navigation would navigate back to the path constructed by '/' + router.basePath + router.flowStartPath, since the modal always opened with the first element selected.

Now, with the ability to open the modal on a specific element, the router.flowStartPath is not necessarily the path for the first element anymore. That's why we should now navigate to router.indexPath instead of the previously used router.flowStartPath.


if (to !== router.currentPath) {
return router.navigate(to);
}
Expand Down
2 changes: 2 additions & 0 deletions packages/types/src/clerk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<UserProfileProps>;
Expand All @@ -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<OrganizationProfileProps>;
Expand Down