KingSora / OverlayScrollbars

A javascript scrollbar plugin that hides the native scrollbars, provides custom styleable overlay scrollbars, and preserves the native functionality and feel.
https://kingsora.github.io/OverlayScrollbars
MIT License
3.71k stars 215 forks source link

[React] does not support router options `scroll: false` configuration in Next.js #654

Closed kwooshung closed 3 weeks ago

kwooshung commented 3 weeks ago

Hello,

I'm experiencing an issue with the OverlayScrollbars library when used in a Next.js application. Specifically, the OverlayScrollbars component does not support the scroll: false configuration for scroll restoration as outlined in the Next.js documentation.

Steps to Reproduce

  1. Set up a Next.js project with OverlayScrollbars integrated.
  2. Configure the Next.js router to disable scroll restoration as described in the Next.js documentation:
  3. Replace the default body scrollbar with OverlayScrollbars and make its content exceed the height to make the scrollbar work.
  4. Add a button at the bottom. Click it to jump to a certain page, but the scroll bar reaches the top.

Demo

  'use client'

  import 'overlayscrollbars/css/OverlayScrollbars.css'
  import { useEffect } from 'react'
  import { useRouter } from 'next/navigation'
  import { OverlayScrollbarsComponent } from 'overlayscrollbars-react'

  const RootLayout = ({children}) => {
      const router = useRouter()

      return (
        <OverlayScrollbarsComponent options={{ scroll: false }}>
            <h1>Content</h1>
            <div style={{ height: '2000px' }}>{children}</div>
            <button
              type="button"
              onClick={() => router.push('/dashboard', { scroll: false })}
            >
              Dashboard
            </button>
        </OverlayScrollbarsComponent>
      );
    };

  export default RootLayout;

Expected Behavior:

When navigating between pages, the scroll position should be reset to the top of the page, as specified by the scroll: false configuration.

Actual Behavior:

The scroll position is not reset, and the previous scroll position is retained when navigating between pages.

KingSora commented 3 weeks ago

Good day @kwooshung

I believe the problem is not that OverlayScrollbars doesnt support this behavior, rather than you are replacing the body scroll container with your own.

In the example you posted the DOM should look something like this:

<html>
  <head>
  </head>
  <body>
    <OverlayScrollbarsComponent>
      <!-- more content -->
    </OverlayScrollbarsComponent>
  </body>
</html>

The OverlayScrollbarsComponent is now essentially taking up all the space and acts now as the scroll container for the entire page. The problem here is that with this setup you essentially replaced the original scroll container. With scroll: false Next.js will now try to reset the scroll position of the original scroll container every time you navigate. This will obviously have no effect, because your new scroll container is the OverlayScrollbarsComponent component.

To fix this issue you have to append OverlayScrollbars to the original scroll container (which is the body element). This is possible in two ways:

  1. In your root Layout file you can initialize the OverlayScrollbarsComponent like this:
<html lang="en" data-overlayscrollbars-initialize="">
  <OverlayScrollbarsComponent element="body">
    {/** your content */}
  </OverlayScrollbarsComponent>
</html>
  1. If you need more control use the useOverlayScrollbars hook in your root Layout like this:
const Layout = () => {
  const [initialize] = useOverlayScrollbars();

  useEffect(() => {
    initialize(document.body);
  }, [initialize]);

  return (
    <html lang="en" data-overlayscrollbars-initialize="">
      <body data-overlayscrollbars-initialize="">
        {/** your content */}
      </body>
    </html>
  );
}

I hope this helps and solves your problem

KingSora commented 3 weeks ago

I've created an small example here: https://stackblitz.com/edit/stackblitz-starters-qfqhsa?file=app%2Flayout.tsx

kwooshung commented 3 weeks ago

Hi @KingSora

The issue has been resolved. After following the suggestions provided, I was able to append OverlayScrollbars to the original scroll container (the body element).Thank you for the guidance and support!

Best regards, kwooshung