Add UI components
This commit is contained in:
95
webui/src/common/components/ProfileMenu/ProfileMenu.jsx
Normal file
95
webui/src/common/components/ProfileMenu/ProfileMenu.jsx
Normal file
@@ -0,0 +1,95 @@
|
||||
import React, {useState, useRef, useEffect, useContext} from 'react';
|
||||
import {UserCircleIcon, SignOutIcon, CaretDownIcon} from '@phosphor-icons/react';
|
||||
import {UserContext} from '@/common/contexts/UserContext.jsx';
|
||||
import './styles.sass';
|
||||
|
||||
export const ProfileMenu = () => {
|
||||
const {logout} = useContext(UserContext);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const menuRef = useRef(null);
|
||||
|
||||
// Close menu when clicking outside
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event) => {
|
||||
if (menuRef.current && !menuRef.current.contains(event.target)) {
|
||||
setIsOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Close menu on escape key
|
||||
useEffect(() => {
|
||||
const handleEscapeKey = (event) => {
|
||||
if (event.key === 'Escape') {
|
||||
setIsOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (isOpen) {
|
||||
document.addEventListener('keydown', handleEscapeKey);
|
||||
return () => {
|
||||
document.removeEventListener('keydown', handleEscapeKey);
|
||||
};
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
const handleLogout = () => {
|
||||
setIsOpen(false);
|
||||
logout();
|
||||
};
|
||||
|
||||
const toggleMenu = () => {
|
||||
setIsOpen(!isOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="profile-menu" ref={menuRef}>
|
||||
<button
|
||||
className={`profile-menu-trigger ${isOpen ? 'active' : ''}`}
|
||||
onClick={toggleMenu}
|
||||
aria-label="User menu"
|
||||
aria-expanded={isOpen}
|
||||
>
|
||||
<div className="profile-menu-avatar">
|
||||
<UserCircleIcon size={16} weight="fill"/>
|
||||
</div>
|
||||
<span className="profile-menu-name">Admin</span>
|
||||
<CaretDownIcon
|
||||
size={14}
|
||||
className={`profile-menu-caret ${isOpen ? 'rotated' : ''}`}
|
||||
/>
|
||||
</button>
|
||||
|
||||
{isOpen && (
|
||||
<div className="profile-menu-dropdown">
|
||||
<div className="profile-menu-header">
|
||||
<div className="profile-menu-avatar profile-menu-avatar--large">
|
||||
<UserCircleIcon size={20} weight="fill"/>
|
||||
</div>
|
||||
<div className="profile-menu-info">
|
||||
<div className="profile-menu-name-large">Admin User</div>
|
||||
<div className="profile-menu-role">Administrator</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="profile-menu-divider"></div>
|
||||
|
||||
<div className="profile-menu-actions">
|
||||
<button
|
||||
className="profile-menu-item"
|
||||
onClick={handleLogout}
|
||||
>
|
||||
<SignOutIcon size={16}/>
|
||||
<span>Sign Out</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
Reference in New Issue
Block a user