UserMenu

Domain

Avatar + name + role trigger (the role line only when the user has one; the email stands in for a missing name); the chevron turns over while the menu is open. Dropdown with Profile, Settings, and Sign out items (hrefs, onClick handlers and labels configurable). extraItems (or items + mergeItems) merge contributed items with the defaults, placed by group and order; a hidden item with a built-in id leaves that item out. portal moves the open menu to document.body so a sticky or clipping top bar cannot cut it off; className goes to the root. Closes on outside click and Escape.

Closed (default)

Preview
Code
<%- include('modules/domain/common/user/UserMenu', {
  name:  user.name,
  email: user.email,
  role:  user.role,
  src:   user.profilePicture,
  profileHref:  '/account/profile',
  settingsHref: '/account/settings',
  signOutHref:  '/auth/logout',
  signOutMethod: 'post'
}) %>

Dropdown open (static preview)

Preview

Alice Johnson

alice@example.com

Code
<!-- Dropdown panel content (shown when open) -->
<%- include('modules/domain/common/user/UserMenu', {
  name:  'Alice Johnson',
  email: 'alice@example.com',
  align: 'right'
}) %>

Contributed items (merged)

Preview
Code
<%# extraItems merge with Profile / Settings / Sign out instead of replacing them.
    No group: joins the account items. No order: after them, before sign out (order 1000). %>
<%- include('modules/domain/common/user/UserMenu', {
  name: user.name,
  email: user.email,
  profileHref: '/me',
  onSignOut: 'signOut()',
  extraItems: [
    { id: 'dnd', label: 'Do not disturb', group: 'status', order: 10 },
    { id: 'preferences', label: 'Preferences', href: '/me/preferences' },
    { id: 'switch-tenant', label: 'Switch workspace', group: 'workspace', order: 600 },
    { id: 'stop-impersonating', label: 'Stop impersonating', group: 'session', order: 900, hidden: !impersonating },
  ]
}) %>

Session user, no Settings, in a portal

Preview
Code
<%# A session user (name + email, no role): the trigger shows the name alone.
    A hidden item with a built-in id leaves Settings out; portal opens the menu in
    document.body so a sticky top bar cannot clip it. %>
<%- include('modules/domain/common/user/UserMenu', {
  name: user.name,
  email: user.email,
  profileHref: '/me',
  signOutHref: '/logout',
  mergeItems: true,
  items: [{ id: 'settings', label: 'Settings', hidden: true }],
  portal: true
}) %>
Source modules/domain/common/user/UserMenu.ejs