Add custom items and links to the <UserButton />
component
The <UserButton />
component supports custom menu items, allowing the incorporation of app-specific settings or additional functionality.
There are two types of custom menu items available:
<UserButton.Action>
- A menu item that triggers an action when clicked.<UserButton.Link>
- A menu item that navigates to a page when clicked.
You can also reorder default items and conditionally render menu items.
<UserButton.Action>
<UserButton.Action />
allows you to add actions to the <UserButton />
component, like opening a chat or triggering a modal.
Props
<UserButton.Action />
accepts the following props:
- Name
label
- Type
string
- Description
The name that will be displayed in the menu of the user button.
- Name
labelIcon
- Type
React.ReactElement
- Description
An icon displayed next to the label in the menu.
- Name
open?
- Type
string
- Description
The path segment that will be used to open the user profile modal to a specific page.
- Name
onClick?
- Type
void
- Description
A function to be called when the menu item is clicked.
Examples
Add an action
The following example adds an "Open chat" action to the <UserButton />
component. When a user selects the <UserButton />
, there will be an "Open chat" menu item.
'use client'
import { UserButton } from '@clerk/nextjs'
const DotIcon = () => {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z" />
</svg>
)
}
export default function Home() {
return (
<header>
<UserButton>
<UserButton.MenuItems>
<UserButton.Action
label="Open chat"
labelIcon={<DotIcon />}
onClick={() => alert('init chat')}
/>
</UserButton.MenuItems>
</UserButton>
</header>
)
}
In Astro components, props are converted to strings, so you can't use an onClick
handler to handle click events. Instead, you can set an arbitrary prop, set up a custom event listener that will check for the value passed to that prop, and then execute a desired action based on that value.
For example, clickIdentifier
is the arbitrary prop being used to identify the click event. Two <UserButton.Action />
components are added to the menu, each with a different clickIdentifier
prop. When the menu item is clicked, the custom event listener will check for the value passed to the clickIdentifier
prop, either "open_chat"
or "open_cart"
, and then execute an action based on that value.
---
import { UserButton } from '@clerk/astro/components'
---
<header>
<UserButton>
<UserButton.MenuItems>
<UserButton.Action label="Open chat" clickIdentifier="open_chat">
<svg
slot="label-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentColor"
>
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</UserButton.Action>
<UserButton.Action label="Open cart" clickIdentifier="open_cart">
<svg
slot="label-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentColor"
>
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</UserButton.Action>
</UserButton.MenuItems>
</UserButton>
</header>
<script>
document.addEventListener('clerk:menu-item-click', (e) => {
if (e.detail === 'open_chat') {
console.log('init chat')
}
if (e.detail === 'open_cart') {
console.log('init cart')
}
})
</script>
To add custom menu items to the <UserButton />
component using the JavaScript SDK, pass the customMenuItems
property to the mountUserButton()
method, as shown in the following example:
import { Clerk } from '@clerk/clerk-js'
// Initialize Clerk with your Clerk Publishable Key
const clerk = new Clerk('YOUR_PUBLISHABLE_KEY')
await clerk.load()
document.getElementById('app').innerHTML = `
<div id="user-button"></div>
`
const userButtonDiv = document.getElementById('user-button')
clerk.mountUserButton(userButtonDiv, {
customMenuItems: [
{
label: 'Help modal',
onClick: () => {
alert('Open modal') // your custom event
},
mountIcon: (el) => {
el.innerHTML = '👤'
},
unmountIcon: (el) => {},
},
],
})
<script setup lang="ts">
import { UserButton } from '@clerk/vue'
function openChat() {
alert('init chat')
}
</script>
<template>
<header>
<UserButton>
<UserButton.MenuItems>
<UserButton.Action label="Open chat" @click="openChat">
<template #labelIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</template>
</UserButton.Action>
</UserButton.MenuItems>
</UserButton>
</header>
</template>
Add an action and a custom page
The following example adds an "Open chat" action to the <UserButton />
component, as well as a custom page titled "Help". When a user selects the <UserButton />
, there will be "Open chat" and "Help" menu items.
'use client'
import { UserButton } from '@clerk/nextjs'
const DotIcon = () => {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z" />
</svg>
)
}
export default function Home() {
return (
<header>
<UserButton>
<UserButton.MenuItems>
<UserButton.Action label="Help" labelIcon={<DotIcon />} open="help" />
</UserButton.MenuItems>
<UserButton.UserProfilePage label="Help" labelIcon={<DotIcon />} url="help">
<div>
<h1>Help Page</h1>
<p>This is the custom help page</p>
</div>
</UserButton.UserProfilePage>
</UserButton>
</header>
)
}
In the following example, the <UserButton.Action />
component is used to add a "Help" menu item to the <UserButton />
component. The open
prop is set to "help"
to open the /help
page when the menu item is selected.
The <UserButton.UserProfilePage />
component is used to render the /help
page, and because its configured as a user profile page, the <UserProfile />
modal will be opened with the custom "Help" menu item. Read more about custom pages.
---
import { UserButton } from '@clerk/astro/components'
---
<header>
<UserButton>
<UserButton.MenuItems>
<UserButton.Action label="Help" open="help">
<svg
slot="label-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentColor"
>
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</UserButton.Action>
</UserButton.MenuItems>
<UserButton.UserProfilePage label="Help" url="help">
<svg
slot="label-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentColor"
>
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
<div>
<h1>Help Page</h1>
<p>This is the custom help page</p>
</div>
</UserButton.UserProfilePage>
</UserButton>
</header>
<script setup lang="ts">
import { UserButton } from '@clerk/vue'
</script>
<template>
<header>
<UserButton>
<UserButton.MenuItems>
<UserButton.Action label="Help" open="help">
<template #labelIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</template>
</UserButton.Action>
</UserButton.MenuItems>
<UserButton.UserProfilePage label="Help" url="help">
<template #labelIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</template>
<div>
<h1>Help Page</h1>
<p>This is the custom help page</p>
</div>
</UserButton.UserProfilePage>
</UserButton>
</header>
</template>
<UserButton.Link>
<UserButton.Link />
allows you to add links to the <UserButton />
component, like custom pages or external URLs.
Props
<UserButton.Link />
accept the following props, all of which are required:
- Name
label
- Type
string
- Description
The name that will be displayed in the menu of the user button.
- Name
labelIcon
- Type
React.ReactElement
- Description
An icon displayed next to the label in the menu.
- Name
href
- Type
string
- Description
The path segment that will be used to navigate to the custom page.
Example
The following example adds a "Create organization" link to the <UserButton />
component. When a user selects the <UserButton />
, there will be a "Create organization" menu item.
'use client'
import { UserButton } from '@clerk/nextjs'
const DotIcon = () => {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z" />
</svg>
)
}
export default function Home() {
return (
<header>
<UserButton>
<UserButton.MenuItems>
<UserButton.Link
label="Create organization"
labelIcon={<DotIcon />}
href="/create-organization"
/>
</UserButton.MenuItems>
</UserButton>
</header>
)
}
---
import { UserButton } from '@clerk/astro/components'
---
<header>
<UserButton>
<UserButton.MenuItems>
<UserButton.Link label="Create organization" href="/create-organization">
<svg
slot="label-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentColor"
>
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</UserButton.Link>
</UserButton.MenuItems>
</UserButton>
</header>
To add custom menu items to the <UserButton />
component using the JavaScript SDK, pass the customMenuItems
property to the mountUserButton()
method, as shown in the following example:
import { Clerk } from '@clerk/clerk-js'
// Initialize Clerk with your Clerk Publishable Key
const clerk = new Clerk('YOUR_PUBLISHABLE_KEY')
await clerk.load()
document.getElementById('app').innerHTML = `
<div id="user-button"></div>
`
const userButtonDiv = document.getElementById('user-button')
clerk.mountUserButton(userButtonDiv, {
customMenuItems: [
{
label: 'User page',
href: '/user',
mountIcon: (el) => {
el.innerHTML = '👤'
},
unmountIcon: (el) => {},
},
],
})
<script setup lang="ts">
import { UserButton } from '@clerk/vue'
</script>
<template>
<header>
<UserButton>
<UserButton.MenuItems>
<UserButton.Link label="Create organization" href="/create-organization">
<template #labelIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</template>
</UserButton.Link>
</UserButton.MenuItems>
</UserButton>
</header>
</template>
Reorder default items
The <UserButton />
component includes two default menu items: Manage account
and Sign out
, in that order. You can reorder these default items by setting the label
prop to 'manageAccount'
or 'signOut'
. This will target the existing default item and allow you to rearrange it.
In the following example, the "Sign out" menu item is moved to the top of the menu, a custom "Create organization" link is added as the second menu item, and the "Manage account" menu item is moved to the bottom of the menu.
'use client'
import { UserButton } from '@clerk/nextjs'
const DotIcon = () => {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z" />
</svg>
)
}
export default function Home() {
return (
<header>
<UserButton>
<UserButton.MenuItems>
<UserButton.Action label="signOut" />
<UserButton.Link
label="Create organization"
labelIcon={<DotIcon />}
href="/create-organization"
/>
<UserButton.Action label="manageAccount" />
</UserButton.MenuItems>
</UserButton>
</header>
)
}
---
import { UserButton } from '@clerk/astro/components'
---
<header>
<UserButton>
<UserButton.MenuItems>
<UserButton.Action label="signOut" />
<UserButton.Link label="Create organization" open="/create-organization">
<svg
slot="label-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentColor"
>
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</UserButton.Link>
<UserButton.Action label="manageAccount" />
</UserButton.MenuItems>
</UserButton>
</header>
<script setup lang="ts">
import { UserButton } from '@clerk/vue'
</script>
<template>
<header>
<UserButton>
<UserButton.MenuItems>
<UserButton.Action label="signOut" />
<UserButton.Link label="Create organization" href="/create-organization">
<template #labelIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</template>
</UserButton.Link>
<UserButton.Action label="manageAccount" />
</UserButton.MenuItems>
</UserButton>
</header>
</template>
Conditionally render menu items
To conditionally render menu items based on a user's role or custom permissions, you can use the has()
helper function.
In the following example, the "Create organization" menu item will only render if the current user has the org:app:admin
permission.
'use client'
import { UserButton, useAuth } from '@clerk/nextjs'
const DotIcon = () => {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z" />
</svg>
)
}
export default function Home() {
const { has, isLoaded } = useAuth()
if (!isLoaded) {
return <span>Loading...</span>
}
const isAdmin = has({ permission: 'org:app:admin' })
return (
<header>
<UserButton>
{isAdmin && (
<UserButton.MenuItems>
<UserButton.Link
label="Create organization"
labelIcon={<DotIcon />}
href="/create-organization"
/>
</UserButton.MenuItems>
)}
</UserButton>
</header>
)
}
---
import { UserButton } from '@clerk/astro/components'
const { has } = Astro.locals.auth()
const isAdmin = has({ permission: 'org:app:admin' })
---
<header>
<UserButton>
{
isAdmin && (
<UserButton.MenuItems>
<UserButton.Link label="Create organization" open="/create-organization">
<svg
slot="label-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentColor"
>
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z" />
</svg>
</UserButton.Link>
</UserButton.MenuItems>
)
}
</UserButton>
</header>
<script setup lang="ts">
import { UserButton, useAuth } from '@clerk/vue'
import { computed } from 'vue'
const { has, isLoaded } = useAuth()
const isAdmin = computed(() => has.value?.({ permission: 'org:app:admin' }))
</script>
<template>
<header v-if="isLoaded && isAdmin">
<UserButton>
<UserButton.MenuItems>
<UserButton.Link label="Create organization" href="/create-organization">
<template #labelIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</template>
</UserButton.Link>
</UserButton.MenuItems>
</UserButton>
</header>
</template>
Feedback
Last updated on