darkroomengineering / lenis

How smooth scroll should be
https://lenis.darkroom.engineering
MIT License
7.35k stars 315 forks source link

ScrollTo smooth scroll not working on anchors #277

Closed sushantgwr87 closed 6 months ago

sushantgwr87 commented 6 months ago

Firstly, this is a great package which I have used before with Next.js Page routing.

Overview and Tested Options

Now since introduction of App Routing in Next.js, issues are arising in scrolling anchors. Well after reading documentation it was mentioned for anchor links scroll, use lenis.scrollTo().

Also checked this issue #217 but didn't helped much.

I am using Next.js 14 and app routing.

Problem

I want to smooth scroll to anchor link, I added lenis separately without wrapping the app, used this codesandbox example for setup, found it here - issue #170 .

Here is a short version I created: codesandbox devbox

Would like to know correct variation or work around this.

clementroche commented 6 months ago

So you're asking how to have smooth anchor scrolling within a react server component ?

You could use a generic function that select all using an anchor link as href

const anchorLinks = [...document.querySelectorAll("a[href]")]
  .filter((a) => a.href.includes('/#'))
  .forEach((a) => {
    a.addEventListener('click', (e) => {
      e.preventDefault()
      const href = '#' + a.href?.split('/#').at(-1)

      lenis.scrollTo(href)
    })
  })
sushantgwr87 commented 6 months ago

So you're asking how to have smooth anchor scrolling within a react server component ?

Yes. 😅 Though not well versed with this app routing and server side yet. Also thanks for quick response.

I added this generic function by creating a client side wrapper component like this:

"use client";
import { useEffect } from "react";
import Lenis from "@studio-freight/lenis";

const Wrapper = ({ children }) => {
  const lenis = new Lenis();

  useEffect(() => {
    const anchorLinks = [...document.querySelectorAll("a[href]")];
    anchorLinks
      .filter((a) => a.href.includes("/#"))
      .forEach((a) => {
        a.addEventListener("click", (e) => {
          e.preventDefault();
          const href = "#" + a.href?.split("/#").at(-1);
          console.log(href);
          lenis.scrollTo(href);
        });
      });
  }, []);

  return <div>{children}</div>;
};

export default Wrapper;

And Navbar link is like this:

<a
      href={"/#about"}
      className="relative text-inherit"
>
      About
 </a>

Though still not working as expected, I can see hashes in console.log but don't understand what is going wrong here as onClicking the link nothing works. I have updated the codesandbox here.

clementroche commented 6 months ago

Codesandbox is just a nightmare working with Next.js... You shouldn't have any issue if you have "use client"

sushantgwr87 commented 6 months ago

@clementroche Thanks for help.

Issue is solved. I just needed to declare lenis in wrapper itself and it worked.