mw10013 / remix-cf-20240202

0 stars 0 forks source link

AutoScroll #2

Closed mw10013 closed 11 months ago

mw10013 commented 11 months ago

https://web.dev/resize-observer/

const ro = new ResizeObserver(entries => {
  document.scrollingElement.scrollTop =
    document.scrollingElement.scrollHeight;
});

// Observe the scrollingElement for when the window gets resized
ro.observe(document.scrollingElement);
// Observe the timeline to process new messages
ro.observe(timeline);

https://usehooks.com/usemeasure

export function useMeasure() {
  const ref = React.useRef(null);
  const [rect, setRect] = React.useState({
    width: null,
    height: null,
  });

  React.useLayoutEffect(() => {
    if (!ref.current) return;

    const observer = new ResizeObserver(([entry]) => {
      if (entry && entry.contentRect) {
        setRect({
          width: entry.contentRect.width,
          height: entry.contentRect.height,
        });
      }
    });

    observer.observe(ref.current);
    return () => {
      observer.disconnect();
    };
  }, []);

  return [ref, rect];
}
mw10013 commented 11 months ago

https://dev.to/martinez/real-scroll-for-a-chat-application-22co

function Chat() {
  const [messages, setMessages] = useState<string[]>([])
  const container = useRef<HTMLDivElement>(null)

  const Scroll = () => {
    const { offsetHeight, scrollHeight, scrollTop } = container.current as HTMLDivElement
    if (scrollHeight <= scrollTop + offsetHeight + 100) {
      container.current?.scrollTo(0, scrollHeight)
    }
  }

  useEffect(() => {
    Scroll()
  }, [messages])

  return <div ref={container}>{messages}</div>
}

https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight

The Element.scrollHeight read-only property is a measurement of the height of an element's content, including content not visible on the screen due to overflow.

https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#determine_if_an_element_has_been_totally_scrolled

scrollTop is a non-rounded number, while scrollHeight and clientHeight are rounded — so the only way to determine if the scroll area is scrolled to the bottom is by seeing if the scroll amount is close enough to some threshold

Math.abs(element.scrollHeight - element.clientHeight - element.scrollTop) < 1;

https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop

An element's scrollTop value is a measurement of the distance from the element's top to its topmost visible content. When an element's content does not generate a vertical scrollbar, then its scrollTop value is 0.

https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetHeight

The HTMLElement.offsetHeight read-only property returns the height of an element, including vertical padding and borders, as an integer.

https://developer.mozilla.org/en-US/docs/Web/API/Element/clientHeight

The Element.clientHeight read-only property is zero for elements with no CSS or inline layout boxes; otherwise, it's the inner height of an element in pixels. It includes padding but excludes borders, margins, and horizontal scrollbars (if present).

mw10013 commented 11 months ago

https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements

If you need to know the total amount of space an element occupies, including the width of the visible content, scrollbars (if any), padding, and border, you want to use the HTMLElement.offsetWidth and HTMLElement.offsetHeight properties.

If you need to know how much space the actual displayed content takes up, including padding but not including the border, margins, or scrollbars, you want to use the Element.clientWidth and Element.clientHeight properties

If you need to know the actual size of the content, regardless of how much of it is currently visible, you need to use the Element.scrollWidth and Element.scrollHeight properties.

mw10013 commented 11 months ago

https://stackoverflow.com/questions/72636816/scroll-to-bottom-when-new-message-added

The trick then lies in reversing the content direction using column-reverse in the scroller. Because the items are in another container, they don't get 'flipped' but instead always line up to the bottom. This, in fact, makes the scroller scrolled to the bottom whenever stuff is added.

whenever the user has started scrolling (up), the scroller will not lose its scroll position when stuff is being added. So, it will only 'stick' tot the bottom if it was already scrolled (by default, or by the user) to the bottom.

https://code.hnldesign.nl/scrolltobottom/

add the items to an item container which is inside a scroller container with display:flex, flex-direction: column-reverse and overflow: scroll (or auto) set.