I'm building a sliding bottom panel as a React component, adapting Phuoc Nguyen's excellent draggable element tutorial.

It currently looks like this:

Draggable element in action

The expected behavior is:

  1. User taps on button to open panel
  2. Panel slides from the bottom up to fill about 90% of the viewport
  3. User can then drag the panel down to close, and when it reaches approx 30% off the top of the viewport it slides down and closes.

Everything appears to be working fine.

I'm interested whether my approach for managing the panel collapse interaction when the handleMouseUp function fires could have been more elegant.

Currently I'm using a setTimeout() to remove style properties from the element which feels like a bit of a hack.

Below is the function in question and here's the component code: https://stackblitz.com/edit/vitejs-vite-7nxqaa?file=src%2FFilter.jsx

Any thoughts would be greatly appreciated!

  H A N D L E  M O U S E  U P

    const handleMouseUp = () => {
      // Gets last dy position after move
      const dy = dyRef.current;

      // Resets dy
      setOffset({ dy: offsetTop });

      // Reassigns animation after moving element
      ele.style.transition = 'transform 0.3s ease-in-out';

      // Conditional to say if the current dy position is greater than the desired tollerance
      // then move the element down off canvas (100vh), reset open state to false, and after that
      // remove the in-line transform property ELSE bounce it back to the top, and keep the open state true
      if (dy > tollerance) {
        ele.style.transform = 'translateY(100vh)';
        setTimeout(() => {
        }, 1);
      } else {
        ele.style.transform = `translateY(${offsetTop}vh)`;
        setTimeout(() => {
        }, 1);

      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.