Skip to main content

Profile Button Components

The template/components/profile-button/ directory implements the user profile button and dropdown menu found in the site header. It displays a user avatar with presence indicator, and opens a dropdown menu with navigation links, role-specific items, and a logout button.

Architecture Overview

Source Files

FileDescription
index.tsxMain ProfileButton component with avatar trigger
profile-menu.tsxDropdown menu container
profile-header.tsxUser info header inside the menu
menu-items.tsxNavigation menu items (admin/user variants)
logout-button.tsxLogout action button

ProfileButton

The main entry point -- a memoized component that renders the user avatar button and manages the dropdown menu lifecycle.

Key Features

  • Lazy loading: ProfileMenu is loaded with React.lazy() and preloaded on hover/focus for faster perceived performance
  • Portal-based loading overlay: Navigation transitions render a full-screen loading overlay via createPortal
  • Keyboard navigation: Escape key closes the menu
  • Backdrop: A semi-transparent backdrop closes the menu on outside click
  • Loading skeleton: Displays a pulsing skeleton while user data loads

Usage

import ProfileButton from '@/components/profile-button';

// In the header component
function Header() {
return (
<nav>
{/* ... other header items */}
<ProfileButton />
</nav>
);
}

Internal Hooks

HookSourcePurpose
useProfileMenu@/hooks/use-profile-menuMenu open/close state, refs
useLogoutOverlay@/hooks/use-logout-overlayLogout handler with overlay
useUserUtils@/hooks/use-user-utilsUser data, role, admin status

ProfileAvatar

A memoized sub-component rendering the user's avatar with online status indicator and admin badge.

Props

PropTypeDefaultDescription
userExtendedUserrequiredUser data object
isAdminbooleanrequiredWhether user has admin role
onlineStatusPresenceStatus"online"Current presence status

Presence Status Colors

StatusColor
onlineGreen with glow shadow
awayYellow with glow shadow
busyRed with glow shadow
offlineGray, no shadow

ProfileMenu

The dropdown container that assembles the header, menu items, and logout button.

Props

PropTypeDescription
isOpenbooleanMenu visibility state
menuRefRefObject<HTMLDivElement>Ref for click-outside detection
userExtendedUser | nullCurrent user data
profilePathstringURL path to user profile
displayRoleRoleLabelUser role display label
onlineStatusPresenceStatusUser presence status
onItemClick() => voidCallback when any menu item is clicked
onNavigationStart() => voidCalled when navigation begins
onNavigationEnd() => voidCalled when navigation completes
isNavigatingbooleanWhether a navigation is in progress
onLogout() => voidLogout handler
logoutTextstringLocalized logout button text
logoutDescriptionstringOptional logout description

ProfileHeader

Displays the user's avatar, name, email, role badge, and online status inside the menu.

Props

PropTypeDescription
userExtendedUserUser data with name, email, image
displayRoleRoleLabelRole label string
onlineStatusPresenceStatusCurrent presence status

Visual Elements

  • Large avatar with ring and shadow
  • Admin crown badge (animated pulse, gradient background)
  • Online/offline status indicator dot
  • Role badge with admin-specific gradient styling
  • Status badge (green for online, gray for offline)

Renders role-appropriate navigation links. Admin users see a comprehensive admin panel menu; regular users see a simplified personal menu.

Admin Menu Items

DestinationIconDescription
/adminSettingsAnalytics Dashboard
/admin/clientsUsersManage Clients
/admin/companiesBuilding2Manage Companies
/admin/collectionsLayersManage Collections
/admin/categoriesFolderTreeCategories
/admin/tagsTagTags
/admin/itemsPackageItems
/admin/surveysFileTextSurveys
/admin/commentsMessageSquareComments
/admin/reportsFlagReports
/admin/rolesShieldRoles
/admin/usersUsersUser Management
/admin/settingsSlidersAdmin Settings

Regular User Menu Items

DestinationIconDescription
{profilePath}UserYour Profile
/client/submissionsFileTextSubmissions
/client/sponsorshipsDollarSignSponsorships
/client/settingsSettingsAccount Settings

LogoutButton

A standalone logout button with loading state management.

Props

PropTypeDescription
onLogout() => void | Promise<void>Async logout handler
logoutTextstringButton label text
logoutDescriptionstringOptional description text

Behavior

  • Shows a loading spinner during logout
  • Keeps loading state active after successful logout (expects redirect)
  • Resets loading on error
  • Uses aria-busy and aria-live="polite" for accessibility

Performance Optimizations

  1. Memoization: All sub-components are wrapped with React.memo() to prevent unnecessary re-renders
  2. Lazy loading: ProfileMenu is loaded with React.lazy() only when the menu opens
  3. Preloading: The menu module is preloaded on hover/focus of the trigger button
  4. Ref-based state: Uses refs alongside state for scroll/loading logic to avoid re-render cascades

Dependencies

  • @/hooks/use-profile-menu -- Menu state management
  • @/hooks/use-logout-overlay -- Logout with overlay
  • @/hooks/use-user-utils -- User data and role utilities
  • @/constants/profile-button.constants -- Size and style constants
  • @/utils/profile-button.utils -- Name formatting, initials generation
  • @/types/profile-button.types -- ExtendedUser, PresenceStatus, RoleLabel