Temzasse / react-modal-sheet

Flexible bottom sheet component built with Framer Motion to provide buttery smooth UX while keeping accessibility in mind 🪐
https://temzasse.github.io/react-modal-sheet/
MIT License
783 stars 74 forks source link

Sheet is too slow at iPhone #163

Open yunjin-kim opened 1 month ago

yunjin-kim commented 1 month ago

device: almost every iPhone version: 17 browser: safari, chrome

react v18 react-dom v18 nextjs v12 react-modal-sheet v3.1.0

why preventScrollMobileSafari this function execute too slow? only iPhone!
that function execute during 1.89sec

this image my iPhone web inspector.

error-img

in your library code

function preventScrollMobileSafari() {
  let scrollable;
  let lastY = 0;
  const onTouchStart = (e) => {
    scrollable = getScrollParent(e.target);
    if (scrollable === document.documentElement && scrollable === document.body) {
      return;
    }
    lastY = e.changedTouches[0].pageY;
  };
  const onTouchMove = (e) => {
    if (scrollable === void 0) {
      return;
    }
    if (scrollable === document.documentElement || scrollable === document.body) {
      e.preventDefault();
      return;
    }
    const y = e.changedTouches[0].pageY;
    const scrollTop = scrollable.scrollTop;
    const bottom = scrollable.scrollHeight - scrollable.clientHeight;
    if (bottom === 0) {
      return;
    }
    if (scrollTop <= 0 && y > lastY || scrollTop >= bottom && y < lastY) {
      e.preventDefault();
    }
    lastY = y;
  };
  const onTouchEnd = (e) => {
    const target = e.target;
    if (willOpenKeyboard(target) && target !== document.activeElement) {
      e.preventDefault();
      target.style.transform = "translateY(-2000px)";
      target.focus();
      requestAnimationFrame(() => {
        target.style.transform = "";
      });
    }
  };
  const onFocus = (e) => {
    const target = e.target;
    if (willOpenKeyboard(target)) {
      target.style.transform = "translateY(-2000px)";
      requestAnimationFrame(() => {
        target.style.transform = "";
        if (visualViewport) {
          if (visualViewport.height < window.innerHeight) {
            requestAnimationFrame(() => {
              scrollIntoView(target);
            });
          } else {
            visualViewport.addEventListener(
              "resize",
              () => {
                scrollIntoView(target);
              },
              { once: true }
            );
          }
        }
      });
    }
  };
  const onWindowScroll = () => {
    window.scrollTo(0, 0);
  };
  const scrollX = window.pageXOffset;
  const scrollY = window.pageYOffset;
  const restoreStyles = chain(
    setStyle(
      document.documentElement,
      "paddingRight",
      `${window.innerWidth - document.documentElement.clientWidth}px`
    ),
    setStyle(document.documentElement, "overflow", "hidden"),
    setStyle(document.body, "marginTop", `-${scrollY}px`)
  );
  window.scrollTo(0, 0);
  const removeEvents = chain(
    addEvent(document, "touchstart", onTouchStart, {
      passive: false,
      capture: true
    }),
    addEvent(document, "touchmove", onTouchMove, {
      passive: false,
      capture: true
    }),
    addEvent(document, "touchend", onTouchEnd, {
      passive: false,
      capture: true
    }),
    addEvent(document, "focus", onFocus, true),
    addEvent(window, "scroll", onWindowScroll)
  );
  return () => {
    restoreStyles();
    removeEvents();
    window.scrollTo(scrollX, scrollY);
  };
}