diff --git a/.changeset/grumpy-kangaroos-ring.md b/.changeset/grumpy-kangaroos-ring.md new file mode 100644 index 00000000000..c9ead6bae4b --- /dev/null +++ b/.changeset/grumpy-kangaroos-ring.md @@ -0,0 +1,26 @@ +--- +'@clerk/vue': patch +--- + +Adds ability to render custom `` links inside `` component. + +Example: + +```vue + + + +``` diff --git a/integration/templates/vue-vite/src/components/CustomUserButton.vue b/integration/templates/vue-vite/src/components/CustomUserButton.vue index 3da06750280..0c42da234c9 100644 --- a/integration/templates/vue-vite/src/components/CustomUserButton.vue +++ b/integration/templates/vue-vite/src/components/CustomUserButton.vue @@ -47,6 +47,14 @@ const isActionClicked = ref(false);

This is the custom terms page

+ + +
Is action clicked: {{ isActionClicked }}
diff --git a/integration/tests/vue/components.test.ts b/integration/tests/vue/components.test.ts index b0eedadd61d..64a8b3835ed 100644 --- a/integration/tests/vue/components.test.ts +++ b/integration/tests/vue/components.test.ts @@ -108,6 +108,36 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withCustomRoles] })('basic te await u.po.expect.toBeSignedOut(); }); + test('render custom user profile pages and links inside user button', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + await u.page.goToRelative('/sign-in'); + await u.po.signIn.waitForMounted(); + await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password }); + await u.po.expect.toBeSignedIn(); + + await u.page.waitForAppUrl('/'); + await u.po.userButton.waitForMounted(); + + // Open UserProfile modal through UserButton + await u.po.userButton.toggleTrigger(); + await u.po.userButton.waitForPopover(); + await u.page.getByRole('menuitem', { name: /Manage account/i }).click(); + await u.po.userProfile.waitForUserProfileModal(); + + // Verify custom pages and links are visible in the UserProfile + await expect(u.page.getByRole('button', { name: /Terms/i })).toBeVisible(); + await expect(u.page.getByRole('button', { name: /Homepage/i })).toBeVisible(); + + // Test custom UserProfilePage is accessible and renders correctly + await u.page.getByRole('button', { name: /Terms/i }).click(); + await expect(u.page.getByRole('heading', { name: 'Custom Terms Page' })).toBeVisible(); + await expect(u.page.getByText('This is the custom terms page')).toBeVisible(); + + // Test UserProfileLink navigation works + await u.page.getByRole('button', { name: /Homepage/i }).click(); + await u.page.waitForAppUrl('/'); + }); + test('render user profile and current user data', async ({ page, context }) => { const u = createTestUtils({ app, page, context }); await u.page.goToRelative('/sign-in'); diff --git a/packages/vue/src/components/ui-components/UserButton/index.ts b/packages/vue/src/components/ui-components/UserButton/index.ts index cfbd1428b09..2620641b229 100644 --- a/packages/vue/src/components/ui-components/UserButton/index.ts +++ b/packages/vue/src/components/ui-components/UserButton/index.ts @@ -8,7 +8,7 @@ import { } from '../../../errors/messages'; import { UserButtonInjectionKey, UserButtonMenuItemsInjectionKey } from '../../../keys'; import type { UserButtonActionProps, UserButtonLinkProps } from '../../../types'; -import { UserProfilePage } from '../UserProfile'; +import { UserProfileLink, UserProfilePage } from '../UserProfile'; import _UserButton from './UserButton.vue'; const MenuItems = defineComponent((_, { slots }) => { @@ -63,4 +63,5 @@ export const UserButton = Object.assign(_UserButton, { Action: MenuAction, Link: MenuLink, UserProfilePage, + UserProfileLink, });