bokuweb / re-resizable

📏 A resizable component for React.
https://bokuweb.github.io/re-resizable/
MIT License
2.44k stars 217 forks source link

Parent scroll resets to 0 when resizing #727

Open naveensenapathi opened 3 years ago

naveensenapathi commented 3 years ago

Overview of the problem

I have a list of elements arranged horizontally with a scroll. When you try to resize any element, the parent scroll resets to 0, making it difficult to see what's happening.

I'm using re-resizable version [6.5.0]

Reproducible on the documentation codesandbox: https://codesandbox.io/s/elegant-banzai-nwliz?file=/src/index.js

My browser is: Google Chrome Version 88.0.4324.192 (Official Build) (x86_64) macOS 11.1

I am sure this issue is not a duplicate after searching the issues for "scroll" issues I found no mention of this behaviour in the documentation.

Description

When there are multiple elements with either a horizontal or a vertical scroll, resizing the element resets the parent scrollLeft and scrollTop values to 0, which makes it difficult to resize elements that go out of the viewport.

Try to resize the 5th or 6th element from the codesandbox example

chrome-capture

Steps to Reproduce

  1. Try to resize the 5th or 6th element from the list of resizable elements

https://codesandbox.io/s/elegant-banzai-nwliz?file=/src/index.js

Expected behavior

It should retain parent's scroll position while resizing

Actual behavior

Parent's scroll resets to 0 obscuring the view of the resizable element

chankim206 commented 3 years ago

In case this helps anyone,

I ran into the same issue however I worked around this issue by utilizing onResizeStart and onResize callbacks

onResizeStart={(e) => {
  const element = e.currentTarget.getBoundingClientRect();
  var topPos = element.top + window.scrollY;
  var leftPos = element.left + window.scrollX;
  pointX.current = leftPos; //just used ref in my case
  pointY.current = topPos;
}}
onResize={(
    event,
    direction,
    refToElement,
    delta,
  ) => {
  window.scrollTo(pointX.current + delta.width, pointY.current + delta.height);
}}

So using onResizeStart to get the position relevant to the view and then during onResize, I utilized the delta to keep it in view as the user resizes.

Hope this helps.

MaxArnaut commented 2 years ago

@chankim206 thank you for the answer!

For the future issuer found easier solution

onResize={(_e, _direction, _ref, data) => {
  if (prevValue.current > data.width) {
    onChange(width + data.width - prevValue.current, height, 100);
  } else {
    onChange(width + Math.abs(data.width - prevValue.current), height, 100);
  }
  prevValue.current = data.width;
}}
onResizeStop={() => {
  prevValue.current = 0;
}} 
tylerkahn commented 1 year ago

Using the above examples as a guide, for my use case this was the simplified solution for the general case.

// Create refs
const parentScrollOffsetX = useRef(0)
const parentScrollOffsetY = useRef(0)
onResizeStart={(e,direction,ref) => {
    parentScrollOffsetX.current = ref.parentElement?.scrollLeft || 0
    parentScrollOffsetY.current = ref.parentElement?.scrollTop || 0
}}
onResize={(e, direction, ref, d) => {
    ref.parentElement.scrollTo(parentScrollOffsetX.current, parentScrollOffsetY.current)
}}
saymon-develop commented 1 year ago

Using the above examples as a guide, for my use case this was the simplified solution for the general case.

// Create refs
const parentScrollOffsetX = useRef(0)
const parentScrollOffsetY = useRef(0)
onResizeStart={(e,direction,ref) => {
    parentScrollOffsetX.current = ref.parentElement?.scrollLeft || 0
    parentScrollOffsetY.current = ref.parentElement?.scrollTop || 0
}}
onResize={(e, direction, ref, d) => {
    ref.parentElement.scrollTo(parentScrollOffsetX.current, parentScrollOffsetY.current)
}}

Same for me, but I use scroll inside resizable area, so I replaced ref.parentElement to myListRef?.current and it's work well too 🙌

francoexequielschuler commented 1 week ago

Hi everyone, any better solution on this? I have tried the proposed solutions but the resizable component keeps setting the parent component scroll position to 0, leading to unwanted layout shifts