Creating a 'Scrollspy' nav with slice machine slices, possible?

Hi

I'm trying to create a nav bar for the slices in my SliceZone. The nav starts part way down the page, sticks to the top, and shows an indication of which 'section' the user is looking at. See this to understand what I mean: Scrollspy · Bootstrap

I have the nav working as it should visually, but the part I'm missing is the indication of the 'active' section.

I found a package which helps with this in React - https://www.npmjs.com/package/react-intersection-observer

It seems the best approach with this React package is to initialise the useInView hook multiple times at the parent container level, and then pass down the ref variables to each child container. The inView variables would then be passed down to the nav to be used to add a class to the active nav item.

The other issue I found with this package is it looks like the 'root' is the document, meaning if the viewport is larger there are often two 'active' sections at once. I would need to set the 'root' to a smaller element - probably the sticky nav bar - so there would be a need to get the ref of this up from the child to the parent.

Is this possible with slice machine slices? I'm not wedded to the particular package mentioned so am very open to other ways I could make this work.

Perhaps this is every bit as much of a React question as it is a Prismic question, but I'm concerned that slice machine is going to make this impossible.

Thanks

Hi David,

I don't know anything about the package that you're working with, but a much easier way to do this would be to add anchor tags to all your H2s and have them serve as your section beginnings. You do this using the HTML serializer as described here:

You would then use an event listener to set the active class on your side menu when the anchor link is in the viewport.

Let me know if this makes sense or if you have any other questions.

Thanks.

Hi Phil

Thanks so much for getting back to me on this.

I've already got the table of contents, which is this case the items on the nav bar. Since the sections will not be changing, it's been pretty easy to list these out in hard-coded fashion.

It's the "set the active class on your side menu when the anchor link is in the viewport" part that I'm having the real issue with.

My side menu is a slice, and each of the sections that are items on the nav are their own slice. Since I'm in React (Next.js specifically), I've been looking at ways to do it involving useRef and useState hooks but am having problems doing it this way due to the opaque nature of the SliceZone component that I'm using in my pages.

I thought earlier along similar lines to what I think you're describing: use the useEffect hook at the page level to listen for scroll and use query selectors to find the elements and update their classes if in view. This solution felt a little hacky though and I was worried about the performance of the event listener executing on every scroll (admittedly my js/react performance knowledge isn't that deep yet so this worry may be unfounded).

What do you think? It would be great if you could give me a nudge in the right direction for how you'd solve this problem?

Much appreciated

Hey again David,

So I found this example of how to do this with pure JS which you can use in Next. You will need to wrap your sections with a <section> tag which has the ID using the title, do this with the HTML Serializer. You can then use the event listener as shown in the JS. With this code, you should be able to do what you're looking for.

Thanks.

Amazing, thanks so much for sharing :slight_smile:

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.