Home > Net >  fadeout sidebar when user doesnt use it for more than 5sec
fadeout sidebar when user doesnt use it for more than 5sec

Time:10-06

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>

  • Related