feat(ui): disable menu buttons with locked param (#1332)

* feat: add lock icon when param `locked=true`

* chore: move `isViewLocked` logic up the component tree

* chore: remove extra container from lock icon

* chore: move fading logic into separate hook

* chore: move locked icon into separate component

* chore: rename variables
This commit is contained in:
asharonbaltazar
2024-11-18 09:49:49 -05:00
committed by GitHub
parent 238eb49b5c
commit 4c88f90a15
5 changed files with 68 additions and 26 deletions
@@ -1,8 +1,7 @@
import { useEffect, useState } from 'react';
import { IoApps } from '@react-icons/all-files/io5/IoApps';
import { IoSettingsOutline } from '@react-icons/all-files/io5/IoSettingsOutline';
import { debounce } from '../../utils/debounce';
import { useFadeOutOnInactivity } from '../../../common/hooks/useFadeOutOnInactivity';
import style from './NavigationMenu.module.scss';
@@ -13,32 +12,10 @@ interface FloatingNavigationProps {
export default function FloatingNavigation(props: FloatingNavigationProps) {
const { toggleMenu, toggleSettings } = props;
const [showButton, setShowButton] = useState(false);
// show on mouse move
useEffect(() => {
let fadeOut: NodeJS.Timeout | null = null;
const setShowMenuTrue = () => {
setShowButton(true);
if (fadeOut) {
clearTimeout(fadeOut);
}
fadeOut = setTimeout(() => setShowButton(false), 3000);
};
const debouncedShowMenu = debounce(setShowMenuTrue, 1000);
document.addEventListener('mousemove', debouncedShowMenu);
return () => {
document.removeEventListener('mousemove', debouncedShowMenu);
if (fadeOut) {
clearTimeout(fadeOut);
}
};
}, []);
const isButtonShown = useFadeOutOnInactivity();
return (
<div className={`${style.buttonContainer} ${!showButton ? style.hidden : ''}`}>
<div className={`${style.buttonContainer} ${!isButtonShown ? style.hidden : ''}`}>
<button
onClick={toggleMenu}
aria-label='toggle menu'
@@ -38,6 +38,16 @@ $button-size: 3rem;
border-radius: 3px;
}
.lockIcon {
font-size: 1.5rem;
display: grid;
place-content: center;
border-radius: 3px;
background-color: transparent;
color: $active-indicator;
cursor: default;
}
.navButton {
@extend .button;
z-index: 3;
@@ -0,0 +1,15 @@
import { IoLockClosedOutline } from '@react-icons/all-files/io5/IoLockClosedOutline';
import { useFadeOutOnInactivity } from '../../../common/hooks/useFadeOutOnInactivity';
import style from './NavigationMenu.module.scss';
export default function ViewLockedIcon() {
const isLockIconShown = useFadeOutOnInactivity();
return (
<div className={`${style.buttonContainer} ${!isLockIconShown ? style.hidden : ''}`}>
<IoLockClosedOutline className={style.lockIcon} />
</div>
);
}
@@ -2,13 +2,18 @@ import { memo, useCallback } from 'react';
import { useSearchParams } from 'react-router-dom';
import { useDisclosure } from '@chakra-ui/react';
import { isStringBoolean } from '../../../features/viewers/common/viewUtils';
import FloatingNavigation from './FloatingNavigation';
import NavigationMenu from './NavigationMenu';
import ViewLockedIcon from './ViewLockedIcon';
function ViewNavigationMenu() {
const [searchParams, setSearchParams] = useSearchParams();
const { isOpen: isMenuOpen, onOpen: onMenuOpen, onClose: onMenuClose } = useDisclosure();
const isViewLocked = isStringBoolean(searchParams.get('locked'));
const showEditFormDrawer = useCallback(() => {
searchParams.set('edit', 'true');
setSearchParams(searchParams);
@@ -16,6 +21,10 @@ function ViewNavigationMenu() {
const toggleMenu = () => (isMenuOpen ? onMenuClose() : onMenuOpen());
if (isViewLocked) {
return <ViewLockedIcon />;
}
return (
<>
<FloatingNavigation toggleMenu={toggleMenu} toggleSettings={showEditFormDrawer} />
@@ -0,0 +1,31 @@
import { useEffect, useState } from 'react';
import { debounce } from '../../common/utils/debounce';
export const useFadeOutOnInactivity = () => {
const [isMouseMoved, setIsMouseMoved] = useState(false);
// show on mouse move
useEffect(() => {
let fadeOut: NodeJS.Timeout | null = null;
const setShowMenuTrue = () => {
setIsMouseMoved(true);
if (fadeOut) {
clearTimeout(fadeOut);
}
fadeOut = setTimeout(() => setIsMouseMoved(false), 3000);
};
const debouncedShowMenu = debounce(setShowMenuTrue, 1000);
document.addEventListener('mousemove', debouncedShowMenu);
return () => {
document.removeEventListener('mousemove', debouncedShowMenu);
if (fadeOut) {
clearTimeout(fadeOut);
}
};
}, []);
return isMouseMoved;
};