Skip to main content
Docs

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:

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.

/app/page.tsx
'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.

pages/index.astro
---
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:

main.js
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) => {},
    },
  ],
})
App.vue
<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.

/app/page.tsx
'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.

pages/index.astro
---
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>
App.vue
<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 /> 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.

/app/page.tsx
'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>
  )
}
pages/index.astro
---
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:

main.js
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) => {},
    },
  ],
})
App.vue
<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.

/app/page.tsx
'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>
  )
}
pages/index.astro
---
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>
App.vue
<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.

/app/page.tsx
'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>
  )
}
pages/index.astro
---
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>
App.vue
<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

What did you think of this content?

Last updated on