Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(clerk-js): Support open userProfile and organizationProfile modals to specific navitems #3732

Merged
Show file tree
Hide file tree
Changes from 12 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
EmmanouelaPothitou marked this conversation as resolved.
Show resolved Hide resolved
"@clerk/types": patch
---

Support opening the userProfileModal and organizationProfileModal to specific navigation items through the userButton and organizationSwitcher.
EmmanouelaPothitou marked this conversation as resolved.
Show resolved Hide resolved
14 changes: 10 additions & 4 deletions packages/clerk-js/src/ui/Components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export const mountComponentRenderer = (clerk: Clerk, environment: EnvironmentRes
void preloadComponent(preloadHint);
}
componentsControlsResolver = import('./lazyModules/common').then(({ createRoot }) => {
createRoot(clerkRoot!).render(
Copy link
Member

Choose a reason for hiding this comment

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

Is this changed by mistake from the linter or it's a conscious change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Linter changed it.

Copy link
Member

Choose a reason for hiding this comment

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

We should revert it then

createRoot(clerkRoot).render(
EmmanouelaPothitou marked this conversation as resolved.
Show resolved Hide resolved
<Components
clerk={clerk}
environment={environment}
Expand Down 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()}
nikosdouvlis marked this conversation as resolved.
Show resolved Hide 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()}
nikosdouvlis marked this conversation as resolved.
Show resolved Hide 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
Member

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
Member

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
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
Loading