import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';
useProfileMenu
A React hook that manages the open/close state, refs, and accessibility behavior for a profile dropdown menu. Handles click-outside dismissal, Escape key closing, and focus restoration to the trigger button.
Import
import { useProfileMenu } from '@/template/hooks/use-profile-menu';
API Reference
Parameters
function useProfileMenu(): UseProfileMenuReturn;
This hook takes no parameters.
Return Value
UseProfileMenuReturn
| Property | Type | Description |
|---|---|---|
isProfileMenuOpen | boolean | Whether the profile dropdown menu is currently visible. |
menuRef | React.RefObject<HTMLDivElement> | Ref to attach to the dropdown menu container element. Used for click-outside detection. |
buttonRef | React.RefObject<HTMLButtonElement> | Ref to attach to the trigger button element. Used for click-outside detection and focus restoration. |
toggleMenu | () => void | Toggles the menu open/closed. Memoized with useCallback. |
closeMenu | () => void | Closes the menu and restores focus to the trigger button. Memoized with useCallback. |
Usage Examples
Basic Profile Dropdown
import { useProfileMenu } from '@/template/hooks/use-profile-menu';
function ProfileDropdown() {
const { isProfileMenuOpen, menuRef, buttonRef, toggleMenu, closeMenu } = useProfileMenu();
return (
<div className="relative">
<button
ref={buttonRef}
onClick={toggleMenu}
aria-expanded={isProfileMenuOpen}
aria-haspopup="true"
>
<img src="/avatar.png" alt="Profile" className="w-8 h-8 rounded-full" />
</button>
{isProfileMenuOpen && (
<div
ref={menuRef}
role="menu"
className="absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg"
>
<a href="/profile" role="menuitem" className="block px-4 py-2">
My Profile
</a>
<a href="/settings" role="menuitem" className="block px-4 py-2">
Settings
</a>
<button
role="menuitem"
onClick={() => {
closeMenu();
handleSignOut();
}}
className="block w-full text-left px-4 py-2"
>
Sign Out
</button>
</div>
)}
</div>
);
}
With Navigation Actions
import { useRouter } from 'next/navigation';
import { useProfileMenu } from '@/template/hooks/use-profile-menu';
function HeaderProfileMenu() {
const router = useRouter();
const { isProfileMenuOpen, menuRef, buttonRef, toggleMenu, closeMenu } = useProfileMenu();
const handleNavigate = (path: string) => {
closeMenu();
router.push(path);
};
return (
<div className="relative">
<button ref={buttonRef} onClick={toggleMenu}>
Profile
</button>
{isProfileMenuOpen && (
<div ref={menuRef} className="absolute right-0 mt-2 w-56 bg-white shadow-lg rounded">
<button onClick={() => handleNavigate('/dashboard')}>Dashboard</button>
<button onClick={() => handleNavigate('/settings')}>Settings</button>
<button onClick={() => handleNavigate('/billing')}>Billing</button>
</div>
)}
</div>
);
}