mirror of
https://github.com/sipeed/NanoKVM.git
synced 2026-09-11 00:22:56 -05:00
ui: update menu bar
This commit is contained in:
@@ -26,9 +26,12 @@ export const Menu = () => {
|
||||
const [menuDisabledItems, setMenuDisabledItems] = useAtom(menuDisabledItemsAtom);
|
||||
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(true);
|
||||
const [isMenuMoved, setIsMenuMoved] = useState(false);
|
||||
const [isMenuHovered, setIsMenuHovered] = useState(true);
|
||||
const [bounds, setBounds] = useState({ left: 0, right: 0, top: 0, bottom: 0 });
|
||||
|
||||
const nodeRef = useRef<any>(null);
|
||||
const nodeRef = useRef<HTMLDivElement | null>(null);
|
||||
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// disabled menu items
|
||||
@@ -51,26 +54,63 @@ export const Menu = () => {
|
||||
};
|
||||
|
||||
handleResize();
|
||||
handleMouseLeave();
|
||||
|
||||
window.addEventListener('resize', handleResize);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
if (timerRef.current) {
|
||||
clearTimeout(timerRef.current);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
function handleMouseEnter() {
|
||||
if (timerRef.current) {
|
||||
clearTimeout(timerRef.current);
|
||||
timerRef.current = null;
|
||||
}
|
||||
setIsMenuHovered(true);
|
||||
}
|
||||
|
||||
function handleMouseLeave() {
|
||||
timerRef.current = setTimeout(() => {
|
||||
setIsMenuHovered(false);
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
return (
|
||||
<Draggable
|
||||
nodeRef={nodeRef}
|
||||
bounds={bounds}
|
||||
handle="strong"
|
||||
positionOffset={{ x: '-50%', y: '0%' }}
|
||||
onStop={(_e, data) => {
|
||||
if (data.x !== 0 || data.y !== 0) {
|
||||
setIsMenuMoved(true);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div ref={nodeRef} className="fixed left-1/2 top-[10px] z-[1000] -translate-x-1/2">
|
||||
<div
|
||||
ref={nodeRef}
|
||||
className="fixed left-1/2 top-[10px] z-[1000] -translate-x-1/2"
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
>
|
||||
{/* Trigger area for auto-show when hidden */}
|
||||
{isMenuOpen && (
|
||||
<div className="absolute -top-[10px] left-0 right-0 h-[60px] w-full bg-transparent" />
|
||||
)}
|
||||
|
||||
<div className="sticky top-[10px] flex w-full justify-center">
|
||||
<div
|
||||
className={clsx(
|
||||
'h-[36px] items-center rounded bg-neutral-800/80',
|
||||
isMenuOpen ? 'flex' : 'hidden'
|
||||
'h-[36px] items-center rounded bg-neutral-800/80 transition-all duration-300',
|
||||
isMenuOpen ? 'flex' : 'hidden',
|
||||
isMenuOpen && !isMenuMoved && !isMenuHovered
|
||||
? '-translate-y-[110%] opacity-80'
|
||||
: 'translate-y-0 opacity-100'
|
||||
)}
|
||||
>
|
||||
<strong>
|
||||
|
||||
@@ -48,7 +48,12 @@ export const Power = () => {
|
||||
}
|
||||
|
||||
const icon = (
|
||||
<div className={clsx('h-[18px] w-[18px]', isPowerOn ? 'text-green-600' : 'text-neutral-300')}>
|
||||
<div
|
||||
className={clsx(
|
||||
'h-[18px] w-[18px]',
|
||||
isPowerOn ? 'text-green-600' : 'text-neutral-300 hover:text-white'
|
||||
)}
|
||||
>
|
||||
{isLoading ? (
|
||||
<LoaderCircleIcon className="animate-spin" size={18} />
|
||||
) : (
|
||||
|
||||
@@ -107,11 +107,11 @@ export const Settings = () => {
|
||||
<>
|
||||
<Tooltip title={t('settings.title')} placement="bottom" mouseEnterDelay={0.6}>
|
||||
<div
|
||||
className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-white hover:bg-neutral-700/80"
|
||||
className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded hover:bg-neutral-700/80"
|
||||
onClick={openModal}
|
||||
>
|
||||
<Badge dot={isUpdateAvailable} color="blue" offset={[0, 2]}>
|
||||
<div className="pt-[3px]">
|
||||
<div className="pt-[3px] text-neutral-300 hover:text-white">
|
||||
<SettingsIcon size={18} />
|
||||
</div>
|
||||
</Badge>
|
||||
|
||||
@@ -213,7 +213,7 @@ export const Wol = () => {
|
||||
return (
|
||||
<MenuItem
|
||||
title={t('wol.title')}
|
||||
icon={<NetworkIcon size={16} />}
|
||||
icon={<NetworkIcon size={18} />}
|
||||
content={content}
|
||||
onOpenChange={handleOpenChange}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user