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

Custom Pages for <UserProfile /> and <OrganizationProfile /> components #1822

Merged
merged 16 commits into from
Oct 24, 2023

Conversation

anagstef
Copy link
Member

@anagstef anagstef commented Oct 3, 2023

Description

This PR introduces custom pages and links inside the UserProfile and OrganizationProfile components.

UserProfile

Custom Pages

The UserProfile component supports the addition of custom pages. These custom pages can be rendered inside the UserProfile component and provide a way to incorporate app-specific settings or additional functionality.

To add a custom page, use the <UserProfile.Page> component. It accepts the following props:

  • label: The name that will be displayed in the navigation sidebar for the custom page.
  • labelIcon: An icon displayed next to the label in the navigation sidebar.
  • url: The path segment that will be used to navigate to the custom page. (e.g. if the UserProfile component is rendered at /user, then the custom page will be accessed at /user/{url} when using path routing)
  • children: The components to be rendered as content inside the custom page.

Types:

type UserProfilePageProps = {
  label: string;
  labelIcon: React.ReactElement;
  url: string;
  children: React.ReactElement;
};

Example usage:

<UserProfile>
  <UserProfile.Page label="Custom Page" url="custom" labelIcon={<CustomIcon />}>
    <MyCustomPageContent />
  </UserProfile.Page>
  <UserProfile.Page label="Custom2" url="custom2" labelIcon={<CustomIcon />}>
    <MyCustomPageContent2 />
  </UserProfile.Page>
</UserProfile>

Custom Links

In addition to custom pages, you can add external links to the UserProfile navigation sidebar using the <UserProfile.Link> component. It accepts the following props:

  • label: The name that will be displayed in the navigation sidebar for the link.
  • labelIcon: An icon displayed next to the label in the navigation sidebar.
  • url: The absolute or relative url to navigate to.

Types:

type UserProfileLinkProps = {
  label: string;
  labelIcon: React.ReactElement;
  url: string;
};

Example usage:

<UserProfile>
  <UserProfile.Link label="External" url="/home" labelIcon={<Icon />} />
</UserProfile>

Advanced

Reordering Default Routes

If you want to reorder the default routes (Account and Security) in the UserProfile navigation sidebar, you can use the <UserProfile.Page> component with the label prop set to 'account' or 'security'. This will target the existing default page and allow you to rearrange it.

Example usage:

<UserProfile>
  <UserProfile.Page label="Custom Page" url="custom" labelIcon={<CustomIcon />}>
    <MyCustomPageContent />
  </UserProfile.Page>
  <UserProfile.Link label="External" url="/home" labelIcon={<Icon />} />
  <UserProfile.Page label="account" />
  <UserProfile.Page label="security" />
</UserProfile>

The above will result in the following order:

  1. Custom Page
  2. External
  3. Account
  4. Security

Notes

  • The first page in the list will be rendered under the root path / (its url will be ignored) and the Clerk pages will be rendered under the path /account.
  • The first item in the list cannot be a <UserProfile.Link> component.

Using custom pages with the UserButton component

If you are using the UserButton component with the default props (where the UserProfile opens as a modal), then you should also be providing these custom pages as children to the component (using the <UserButton.UserProfilePage> and <UserButton.UserProfileLink> components respectively).

Example usage:

<UserButton afterSignOutUrl='/'>
  <UserButton.UserProfilePage 
		label="Custom" 
		url="custom" 
		labelIcon={<CustomIcon />}
	>
    <MyCustomPageContent />
  </UserButton.UserProfilePage>
	<UserButton.UserProfileLink label="Link" url="/home" labelIcon={<Icon />} />
</UserButton>

This repetition of the same property can be avoided when the user is using the userProfileMode='navigation' and userProfileUrl='<some url>' props on the UserButton component and has implemented a dedicated page for the UserProfile component.

OrganizationProfile

Custom Pages

The OrganizationProfile component supports the addition of custom pages. These custom pages can be rendered inside the OrganizationProfile component and provide a way to incorporate organization-specific settings or additional functionality.

To add a custom page, use the <OrganizationProfile.Page> component. It accepts the following props:

  • label: The name that will be displayed in the navigation sidebar for the custom page.
  • labelIcon: An icon displayed next to the label in the navigation sidebar.
  • url: The path segment that will be used to navigate to the custom page. (e.g. if the OrganizationProfile component is rendered at /organization, then the custom page will be accessed at /organization/{url} when using path routing)
  • children: The components to be rendered as content inside the custom page.

Types:

type OrganizationProfilePageProps = {
  label: string;
  labelIcon: React.ReactElement;
  url: string;
  children: React.ReactElement;
};

Example usage:

<OrganizationProfile>
  <OrganizationProfile.Page label="Custom Page" url="custom" labelIcon={<CustomIcon />}>
    <MyCustomPageContent />
  </OrganizationProfile.Page>
  <OrganizationProfile.Page label="Custom2" url="custom2" labelIcon={<CustomIcon />}>
    <MyCustomPageContent2 />
  </OrganizationProfile.Page>
</OrganizationProfile>

Custom Links

In addition to custom pages, you can add external links to the OrganizationProfile navigation sidebar using the <OrganizationProfile.Link> component. It accepts the following props:

  • label: The name that will be displayed in the navigation sidebar for the link.
  • labelIcon: An icon displayed next to the label in the navigation sidebar.
  • url: The absolute or relative url to navigate to.

Types:

type OrganizationProfileLinkProps = {
  label: string;
  labelIcon: React.ReactElement;
  url: string;
};

Example usage:

<OrganizationProfile>
  <OrganizationProfile.Link label="External" url="/home" labelIcon={<Icon />} />
</OrganizationProfile>

Advanced

Reordering Default Routes

If you want to reorder the default routes (Members and Settings) in the OrganizationProfile navigation sidebar, you can use the <OrganizationProfile.Page> component with the label prop set to 'members' or 'settings'. This will target the existing default page and allow you to rearrange it.

Example usage:

<OrganizationProfile>
  <OrganizationProfile.Page label="Custom Page" url="custom" labelIcon={<CustomIcon />}>
    <MyCustomPageContent />
  </OrganizationProfile.Page>
  <OrganizationProfile.Link label="External" url="/home" labelIcon={<Icon />} />
  <OrganizationProfile.Page label="members" />
  <OrganizationProfile.Page label="settings" />
</OrganizationProfile>

The above will result in the following order:

  1. Custom Page
  2. External
  3. Members
  4. Settings

Notes

  • The first page in the list will be rendered under the root path / (its url will be ignored) and the Clerk pages will be rendered under the path /organitzation-members and /organization-settings.
  • The first item in the list cannot be an <OrganizationProfile.Link> component.

Using custom pages with the OrganizationSwitcher component

If you are using the OrganizationSwitcher component with the default props (where the OrganizationProfile opens as a modal), then you should also be providing these custom pages as children to the component (using the <OrganizationSwitcher.OrganizationProfilePage> and <OrganizationSwitcher.OrganizationProfileLink> components respectively).

Example usage:

<OrganizationSwitcher>
  <OrganizationSwitcher.OrganizationProfilePage
    label="Custom"
    url="custom"
    labelIcon={<CustomIcon />}
  >
    <MyCustomPageContent />
  </OrganizationSwitcher.OrganizationProfilePage>
  <OrganizationSwitcher.OrganizationProfileLink label="Link" url="/home" labelIcon={<Icon />} />
</OrganizationSwitcher>

This repetition of the same property can be avoided when the user is using the organizationProfileMode='navigation' and organizationProfileUrl='<some url>' props on the OrganizationSwitcher component and has implemented a dedicated page for the OrganizationProfile component.

Caveats

  • These custom components can be rendered only on the client, and in Next.js projects, they need to be under the "use client"; flag.

Checklist

  • npm test runs as expected.
  • npm run build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Packages affected

  • @clerk/clerk-js
  • @clerk/clerk-react
  • @clerk/nextjs
  • @clerk/remix
  • @clerk/types
  • @clerk/themes
  • @clerk/localizations
  • @clerk/clerk-expo
  • @clerk/backend
  • @clerk/clerk-sdk-node
  • @clerk/shared
  • @clerk/fastify
  • @clerk/chrome-extension
  • gatsby-plugin-clerk
  • build/tooling/chore

@anagstef anagstef requested a review from a team as a code owner October 3, 2023 14:45
@changeset-bot
Copy link

changeset-bot bot commented Oct 3, 2023

🦋 Changeset detected

Latest commit: 3d8b86a

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

This PR includes changesets to release 12 packages
Name Type
@clerk/clerk-js Minor
@clerk/clerk-react Minor
@clerk/types Minor
@clerk/chrome-extension Patch
@clerk/clerk-expo Patch
gatsby-plugin-clerk Patch
@clerk/nextjs Patch
@clerk/remix Patch
@clerk/backend Patch
@clerk/fastify Patch
@clerk/localizations Patch
@clerk/clerk-sdk-node Patch

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

@anagstef anagstef changed the title Custom Pages for UserProfile Custom Pages for UserProfile component Oct 3, 2023
@anagstef anagstef self-assigned this Oct 3, 2023
@anagstef
Copy link
Member Author

anagstef commented Oct 3, 2023

!snapshot

@clerk-cookie
Copy link
Collaborator

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

Package Version
@clerk/backend 0.30.2-snapshot.875725a
@clerk/chrome-extension 0.4.5-snapshot.875725a
@clerk/clerk-js 4.60.0-snapshot.875725a
@clerk/clerk-expo 0.19.7-snapshot.875725a
@clerk/fastify 0.6.12-snapshot.875725a
gatsby-plugin-clerk 4.4.13-snapshot.875725a
@clerk/localizations 1.26.3-snapshot.875725a
@clerk/nextjs 4.25.2-snapshot.875725a
@clerk/clerk-react 4.27.0-snapshot.875725a
@clerk/remix 3.0.4-snapshot.875725a
@clerk/clerk-sdk-node 4.12.11-snapshot.875725a
@clerk/shared 0.24.2-snapshot.875725a
@clerk/themes 1.7.7-snapshot.875725a
@clerk/types 3.54.0-snapshot.875725a

Tip: use the snippet copy button below to quickly install the required packages.

# @clerk/backend
npm i @clerk/[email protected]
# @clerk/chrome-extension
npm i @clerk/[email protected]
# @clerk/clerk-js
npm i @clerk/[email protected]
# @clerk/clerk-expo
npm i @clerk/[email protected]
# @clerk/fastify
npm i @clerk/[email protected]
# gatsby-plugin-clerk
npm i [email protected]
# @clerk/localizations
npm i @clerk/[email protected]
# @clerk/nextjs
npm i @clerk/[email protected]
# @clerk/clerk-react
npm i @clerk/[email protected]
# @clerk/remix
npm i @clerk/[email protected]
# @clerk/clerk-sdk-node
npm i @clerk/[email protected]
# @clerk/shared
npm i @clerk/[email protected]
# @clerk/themes
npm i @clerk/[email protected]
# @clerk/types
npm i @clerk/[email protected]

export type UserProfilePageProps = {
url?: string;
label: string;
labelIcon?: React.ReactElement;
Copy link
Member

Choose a reason for hiding this comment

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

❓ Couldn't this be ReactNode ?

Copy link
Member

@BRKalow BRKalow left a comment

Choose a reason for hiding this comment

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

Looking good! Nice test cases.

<Route
index={!pages.isAccountPageRoot && index === 0}
path={!pages.isAccountPageRoot && index === 0 ? undefined : customPage.url}
key={`custom-page-${index}`}
Copy link
Member

Choose a reason for hiding this comment

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

💭 I don't expect the custom pages list to change really, but using url in the key might be better here.

const { queryParams } = useRouter();

if (componentName !== 'UserProfile') {
throw new Error('Clerk: useUserProfileContext called outside of the mounted UserProfile component.');
}

const pages = useMemo(() => createCustomPages(customPages || []), [customPages]);
Copy link
Member

Choose a reason for hiding this comment

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

❓ Is customPages memoized upstream from this? Otherwise, this useMemo() call might be getting recomputed on every call to this hook.

Copy link
Member

Choose a reason for hiding this comment

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

From what I can tell, there isn't anything that guarantees referential equality of customPages, so this might run more than we intend.

Copy link
Member Author

Choose a reason for hiding this comment

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

You are right! We cannot hook on the customPages changes, because we can't really be 100% sure when custom pages contents change. So, I may just remove the useMemo here.

@@ -43,13 +43,21 @@ const getSectionId = (id: RouteId) => `#cl-section-${id}`;

export const NavBar = (props: NavBarProps) => {
const { contentRef, routes, header } = props;
const [activeId, setActiveId] = React.useState<RouteId>(routes[0]['id']);
const [activeId, setActiveId] = React.useState<RouteId>('');
Copy link
Member

Choose a reason for hiding this comment

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

❓ Why are we removing this default value?

Copy link
Member Author

Choose a reason for hiding this comment

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

This was causing a flicker when accessing directly a subpath in the UserProfile. In the first render, it always highlighted the first item in the navbar and then changed to the actual active. Now, it highlights nothing for half a second and then the correct item, which looks smoother in the eye.

Comment on lines 21 to 23
<>
<div ref={nodeRef}></div>
</>
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
<>
<div ref={nodeRef}></div>
</>
<div ref={nodeRef} />

Comment on lines 37 to 78
if (isDevelopmentEnvironment()) {
checkForDuplicateUsageOfReorderingItems(customPages);
}
Copy link
Member

Choose a reason for hiding this comment

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

love the helpful error checks here 👏

};

const checkForDuplicateUsageOfReorderingItems = (customPages: CustomPage[]) => {
const reorderItems = customPages.filter(cp => isAccountReorderItem(cp) || isSecurityReorderItem(cp));
Copy link
Member

Choose a reason for hiding this comment

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

Just thinking for the future, if we ever add another internal page that can be reordered, we'll have a few places that need updating. Is there a way we can consolidate that logic?

Copy link
Member Author

Choose a reason for hiding this comment

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

I have refactored this part. Thanks for pointing out.

Comment on lines 179 to 238
const sanitizeCustomPageURL = (url: string): string => {
if (!url) {
throw new Error('URL is required for custom pages');
}
if (isValidUrl(url)) {
throw new Error('Absolute URLs are not supported for custom pages');
}
return (url as string).charAt(0) === '/' && (url as string).length > 1 ? (url as string).substring(1) : url;
};

const sanitizeCustomLinkURL = (url: string): string => {
if (!url) {
throw new Error('URL is required for custom links');
}
if (isValidUrl(url)) {
return url;
}
return (url as string).charAt(0) === '/' ? url : `/${url}`;
};
Copy link
Member

Choose a reason for hiding this comment

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

❓ Why are we removing the leading / in one of these methods and prepending it in another?

Copy link
Member Author

Choose a reason for hiding this comment

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

We want the Custom Link items (external links) to have a leading / so that navigate works correctly, and on the other hand Custom Page items need a relative segment, to navigate inside the UserProfile/OrganizationProfile routing mechanism.

Comment on lines 104 to 152
export function UserProfilePage({ children }: PropsWithChildren<UserProfilePageProps>) {
if (isDevelopmentEnvironment()) {
console.error(userProfilePageRenderedError);
}
return <div>{children}</div>;
}

export function UserProfileLink({ children }: PropsWithChildren<UserProfileLinkProps>) {
if (isDevelopmentEnvironment()) {
console.error(userProfileLinkRenderedError);
}
return <div>{children}</div>;
}
Copy link
Member

Choose a reason for hiding this comment

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

Should we not export these instead of logging an error when they are used directly?

Copy link
Member Author

Choose a reason for hiding this comment

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

We don't export them from our package. We do this so we can import it in the useCustomPages hook, and check if this is the component used as a child inside the UserProfile

ref: https://github.com/clerkinc/javascript/blob/3bf4d1a78916f24b47d094cbf97065e510d3f337/packages/react/src/utils/useCustomPages.tsx#L69

Comment on lines 132 to 133
Page: ({ children }: PropsWithChildren<UserProfilePageProps>) => React.JSX.Element;
Link: ({ children }: PropsWithChildren<UserProfileLinkProps>) => React.JSX.Element;
Copy link
Member

Choose a reason for hiding this comment

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

Does this work?

Suggested change
Page: ({ children }: PropsWithChildren<UserProfilePageProps>) => React.JSX.Element;
Link: ({ children }: PropsWithChildren<UserProfileLinkProps>) => React.JSX.Element;
Page: typeof UserProfilePage;
Link: typeof UserProfileLink;

Copy link
Member

Choose a reason for hiding this comment

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

It might also be helpful to place these types at the top of the file, instead of interleaved with the source.

Comment on lines 105 to 107
if (isDevelopmentEnvironment()) {
console.error(userProfilePageRenderedError);
}
Copy link
Member

Choose a reason for hiding this comment

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

Your errorInDevMode helper could be used here.

@anagstef anagstef changed the title Custom Pages for UserProfile component Custom Pages for UserProfile and OrganizationProfile components Oct 5, 2023
@anagstef
Copy link
Member Author

anagstef commented Oct 5, 2023

!snapshot

@clerk-cookie
Copy link
Collaborator

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

Package Version
@clerk/backend 0.30.2-snapshot.3bf4d1a
@clerk/chrome-extension 0.4.5-snapshot.3bf4d1a
@clerk/clerk-js 4.60.0-snapshot.3bf4d1a
@clerk/clerk-expo 0.19.7-snapshot.3bf4d1a
@clerk/fastify 0.6.12-snapshot.3bf4d1a
gatsby-plugin-clerk 4.4.13-snapshot.3bf4d1a
@clerk/localizations 1.26.3-snapshot.3bf4d1a
@clerk/nextjs 4.25.2-snapshot.3bf4d1a
@clerk/clerk-react 4.27.0-snapshot.3bf4d1a
@clerk/remix 3.0.4-snapshot.3bf4d1a
@clerk/clerk-sdk-node 4.12.11-snapshot.3bf4d1a
@clerk/shared 0.24.2-snapshot.3bf4d1a
@clerk/themes 1.7.7-snapshot.3bf4d1a
@clerk/types 3.54.0-snapshot.3bf4d1a

Tip: use the snippet copy button below to quickly install the required packages.

# @clerk/backend
npm i @clerk/[email protected]
# @clerk/chrome-extension
npm i @clerk/[email protected]
# @clerk/clerk-js
npm i @clerk/[email protected]
# @clerk/clerk-expo
npm i @clerk/[email protected]
# @clerk/fastify
npm i @clerk/[email protected]
# gatsby-plugin-clerk
npm i [email protected]
# @clerk/localizations
npm i @clerk/[email protected]
# @clerk/nextjs
npm i @clerk/[email protected]
# @clerk/clerk-react
npm i @clerk/[email protected]
# @clerk/remix
npm i @clerk/[email protected]
# @clerk/clerk-sdk-node
npm i @clerk/[email protected]
# @clerk/shared
npm i @clerk/[email protected]
# @clerk/themes
npm i @clerk/[email protected]
# @clerk/types
npm i @clerk/[email protected]

@anagstef
Copy link
Member Author

anagstef commented Oct 6, 2023

!snapshot

@clerk-cookie
Copy link
Collaborator

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

Package Version
@clerk/backend 0.30.3-snapshot.09b5917
@clerk/chrome-extension 0.4.6-snapshot.09b5917
@clerk/clerk-js 4.61.0-snapshot.09b5917
@clerk/clerk-expo 0.19.8-snapshot.09b5917
@clerk/fastify 0.6.13-snapshot.09b5917
gatsby-plugin-clerk 4.4.14-snapshot.09b5917
@clerk/localizations 1.26.4-snapshot.09b5917
@clerk/nextjs 4.25.3-snapshot.09b5917
@clerk/clerk-react 4.27.0-snapshot.09b5917
@clerk/remix 3.0.5-snapshot.09b5917
@clerk/clerk-sdk-node 4.12.12-snapshot.09b5917
@clerk/shared 0.24.3-snapshot.09b5917
@clerk/types 3.55.0-snapshot.09b5917

Tip: use the snippet copy button below to quickly install the required packages.

# @clerk/backend
npm i @clerk/[email protected]
# @clerk/chrome-extension
npm i @clerk/[email protected]
# @clerk/clerk-js
npm i @clerk/[email protected]
# @clerk/clerk-expo
npm i @clerk/[email protected]
# @clerk/fastify
npm i @clerk/[email protected]
# gatsby-plugin-clerk
npm i [email protected]
# @clerk/localizations
npm i @clerk/[email protected]
# @clerk/nextjs
npm i @clerk/[email protected]
# @clerk/clerk-react
npm i @clerk/[email protected]
# @clerk/remix
npm i @clerk/[email protected]
# @clerk/clerk-sdk-node
npm i @clerk/[email protected]
# @clerk/shared
npm i @clerk/[email protected]
# @clerk/types
npm i @clerk/[email protected]

@@ -12,65 +14,87 @@ import { VerifiedDomainPage } from './VerifiedDomainPage';
import { VerifyDomainPage } from './VerifyDomainPage';

export const OrganizationProfileRoutes = (props: PropsOfComponent<typeof ProfileCardContent>) => {
const { pages } = useOrganizationProfileContext();
const isMembersPageRoot = pages.routes[0].id === 'members';
Copy link
Contributor

Choose a reason for hiding this comment

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

Any chance this array is empty?

Copy link
Member Author

Choose a reason for hiding this comment

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

No chance; it always appends Clerk default routes.

Copy link
Contributor

Choose a reason for hiding this comment

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

❓ is there a way to use a constant or enum instead of hard-coding members?

path='profile'
flowStart
index={!isPredefinedPageRoot && index === 0}
path={!isPredefinedPageRoot && index === 0 ? undefined : customPage.url}
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we extract this condition and give it some context with a good variable name?

packages/types/src/clerk.ts Outdated Show resolved Hide resolved
Comment on lines -97 to -98
export type NavbarItemId = 'account' | 'security' | 'members' | 'settings';

Copy link
Member

Choose a reason for hiding this comment

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

If we are interested in keeping this we could do

export type NavbarItemId = 'account' | 'security' | 'members' | 'settings' | (string & {});

Copy link
Member Author

Choose a reason for hiding this comment

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

Does it make sense to keep this?

Comment on lines 31 to 32

const portal = () => <>{nodes[index] ? createPortal(el.component, nodes[index] as Element) : null}</>;
Copy link
Member

Choose a reason for hiding this comment

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

🤔 Is it a common pattern to have a react hook returning JSX ?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think it's not that common, but we need this to be updated on each render. Do you have any suggestions on different approaches?

packages/react/src/utils/useCustomElementPortal.tsx Outdated Show resolved Hide resolved
packages/react/src/utils/errorInDevMode.ts Outdated Show resolved Hide resolved
packages/react/src/components/uiComponents.tsx Outdated Show resolved Hide resolved
packages/react/src/components/uiComponents.tsx Outdated Show resolved Hide resolved
Comment on lines 20 to 28
type UserProfileCustomPage = {
label: string;
url: string;
mountIcon: (el: HTMLDivElement) => void;
unmountIcon: (el?: HTMLDivElement) => void;
mount: (el: HTMLDivElement) => void;
unmount: (el?: HTMLDivElement) => void;
};
Copy link
Member

Choose a reason for hiding this comment

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

🙃

Suggested change
type UserProfileCustomPage = {
label: string;
url: string;
mountIcon: (el: HTMLDivElement) => void;
unmountIcon: (el?: HTMLDivElement) => void;
mount: (el: HTMLDivElement) => void;
unmount: (el?: HTMLDivElement) => void;
};
type UserProfileCustomPage = CustomPage

Copy link
Member Author

Choose a reason for hiding this comment

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

This is a different type. CustomPage is more generic for all three types of custom items (pages, links, reordering), which is why all of its properties except label are optional.

@anagstef anagstef changed the title Custom Pages for UserProfile and OrganizationProfile components Custom Pages for <UserProfile /> and <OrganizationProfile /> components Oct 12, 2023
@anagstef
Copy link
Member Author

!snapshot

@clerk-cookie
Copy link
Collaborator

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

Package Version
@clerk/backend 0.30.3-snapshot.93fdf20
@clerk/chrome-extension 0.4.6-snapshot.93fdf20
@clerk/clerk-js 4.61.0-snapshot.93fdf20
@clerk/clerk-expo 0.19.8-snapshot.93fdf20
@clerk/fastify 0.6.13-snapshot.93fdf20
gatsby-plugin-clerk 4.4.14-snapshot.93fdf20
@clerk/localizations 1.26.4-snapshot.93fdf20
@clerk/nextjs 4.25.3-snapshot.93fdf20
@clerk/clerk-react 4.27.0-snapshot.93fdf20
@clerk/remix 3.0.5-snapshot.93fdf20
@clerk/clerk-sdk-node 4.12.12-snapshot.93fdf20
@clerk/shared 0.24.3-snapshot.93fdf20
@clerk/types 3.55.0-snapshot.93fdf20

Tip: use the snippet copy button below to quickly install the required packages.

# @clerk/backend
npm i @clerk/[email protected]
# @clerk/chrome-extension
npm i @clerk/[email protected]
# @clerk/clerk-js
npm i @clerk/[email protected]
# @clerk/clerk-expo
npm i @clerk/[email protected]
# @clerk/fastify
npm i @clerk/[email protected]
# gatsby-plugin-clerk
npm i [email protected]
# @clerk/localizations
npm i @clerk/[email protected]
# @clerk/nextjs
npm i @clerk/[email protected]
# @clerk/clerk-react
npm i @clerk/[email protected]
# @clerk/remix
npm i @clerk/[email protected]
# @clerk/clerk-sdk-node
npm i @clerk/[email protected]
# @clerk/shared
npm i @clerk/[email protected]
# @clerk/types
npm i @clerk/[email protected]

@anagstef anagstef added this pull request to the merge queue Oct 24, 2023
Merged via the queue into main with commit 51861ad Oct 24, 2023
12 checks passed
@anagstef anagstef deleted the js-621-rfc-poc branch October 24, 2023 01:47
@clerk-cookie clerk-cookie mentioned this pull request Oct 24, 2023
@clerk-cookie
Copy link
Collaborator

This PR has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@clerk clerk locked as resolved and limited conversation to collaborators Oct 24, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants