Expected Scenario: if the user doesn't use the sidebar for more than 5 seconds, the sidebar fadeout (opacity set to 20%) and fade in (opacity:100%) when mouse is 20px nearby.
Current implementation what i got is: when I load the page and on sidebar if its not hovered for 5 sec, its faded out and when i hover on it, it fades in (opacity 100%) and when i hover out (mouseleave) it is 100%.
I am failing to achieve when mouse is 20px nearby - fade in.
const [isSidebarFaded, setSidebarFaded] = useState(false)
const [isHovered, setHovered] = useState(false)
useEffect(() => {
if (!isHovered) {
const timerId = setTimeout(() => {
//after 5 seconds if not hovered
setSidebarFaded(true)
}, 5000)
return () => {
clearTimeout(timerId)
}
}
}, [])
const handleMouseEnter = () => {
setHovered(true)
if (isSidebarFaded) {
setSidebarFaded(false)
}
}
const handleMouseLeave = () => {
setHovered(false)
if (isSidebarFaded)
setSidebarFaded(true)
}
return(
<div
className={classNames(styles.component, {
[styles.fadeOut]: isSidebarFaded,
})}
onm ouseEnter={handleMouseEnter}
onm ouseLeave={handleMouseLeave}
>
)
CodePudding user response:
Create a wrapper around the actual sidebar, with a padding of 20px
. Put the event handlers on the wrapper.
In my version of your code, there is a single timeout with ref, that the event handlers start/stop:
const { useState, useRef, useCallback, useEffect } = React
const Demo = () => {
const [isSidebarFaded, setSidebarFaded] = useState(false)
const timeout = useRef()
const handleMouseEnter = useCallback(() => {
setSidebarFaded(false)
clearTimeout(timeout.current)
}, [])
const handleMouseLeave = useCallback(() => {
clearTimeout(timeout.current)
timeout.current = setTimeout(() => {
setSidebarFaded(true)
}, 2000)
}, [])
useEffect(() => {
handleMouseLeave();
return () => {
clearTimeout(timeout.current)
}
}, [handleMouseLeave])
return(
<div
className={classNames({ sidebarContainer: true, sidebarFaded: isSidebarFaded })}
onm ouseEnter={handleMouseEnter}
onm ouseLeave={handleMouseLeave}
>
<div className="sidebar"></div>
</div>
)
}
ReactDOM
.createRoot(root)
.render(<Demo />)
.sidebarContainer {
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: 100px;
padding-right: 20px;
opacity: 1;
transition: opacity 0.3s;
}
.sidebarFaded {
opacity: 0.2;
}
.sidebar {
height: 100%;
width: 100%;
background: blue;
}
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/classnames/2.3.2/index.min.js" integrity="sha512-GqhSAi WYQlHmNWiE4TQsVa7HVKctQMdgUMA 1RogjxOPdv9Kj59/no5BEvJgpvuMTYw2JRQu/szumfVXdowag==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div id="root"></div>