#Scroll persistence for cross-page list of links

18 messages ยท Page 1 of 1 (latest)

covert latch
#

I have a layout that has a long list of links pinned to the right, then on click 'slides' to the left via a view transition and renders that item's content to the right. That list has a scroll, and jumps back to top on navigate between the base page and the detail page.

base page/layout:
[ calendar ] [ events list ]

detail page/layout:
[ events list ] [ details ]

How can I persist scroll on the events list between page navigation without jeopradising the view transition? I've tried using the lifecycle hooks like before-swap and after-swap but that breaks the view transition for some reason. Also the transition:persist doesn't work for that either.

dim scroll
#

Hi @covert latch ๐Ÿ‘‹

transition:persist should work for your use case. Make sure, you also give it a name. Try setting transition:persist="event-list" on the list.

If this doesn't work, do you have a repository I can take a look at?

covert latch
dim scroll
#

I tried the link above in different browsers and I can see the list moving left and right when I switch between the calendar and the details view. So I assume "close, but no cigar" means you would have expected this to look different?

dim scroll
#

@covert latch ๐Ÿ‘†

clear jolt
#

The issue is that when you navigate the scroll position of the page isn't remembered ?

#
<script>
    document.addEventListener("astro:after-swap", () => {
        scrollTo({ top: history.state.scrollY, behavior: "instant" });
    });
</script>
dim scroll
clear jolt
dim scroll
# clear jolt hehe I got it from you https://discord.com/channels/830184174198718474/830184175...

Haha ๐Ÿคฆโ€โ™‚๏ธ yes, that was written and back-linked a bit ambiguously. I was not aware that Josh has a scrolling issue. My guess is rather that they imagine the effect differently. For example, that the list might look nicer if it slides, perhaps staying in the foreground or something along those lines. Without a reply from the @covert latch, I am just fumbling around in the dark.

The code you copied is great for overriding smooth scrolling with instant scrolling. What I meant in my comment is this: normal scroll restoration itself is something the client router should be able to handle without any extra help ๐Ÿค“

clear jolt
#

I read this:

That list has a scroll, and jumps back to top on navigate between the base page and the detail page.

And understood the issue is that during navigation the page always scrolls back to the top. But I could be wrong.

covert latch
dim scroll
# covert latch The events column is the only thing on the page that scrolls and thatโ€™s what jum...

Hi @covert latch :๐Ÿ‘‹ I got a chance to look at your code. Persisting #ftEventsList is problematic as it a) would not update the Calender/Details toggle at the top of the list and b) loses transition:* information as the list changes its position in the DOM when switching to the detail view.

I guess, the correct way for your site is to just persist the div that has the scroll bar, which is in EventsColumn.astro

- 97 <div class="flex min-w-0 flex-col h-full min-h-0 overflow-x-hidden overflow-y-auto">
+ 97 <div class="flex min-w-0 flex-col h-full min-h-0 overflow-x-hidden overflow-y-auto" transition:persist="scrolled-list" >

Do you want to give that a try?

covert latch
dim scroll
# covert latch Problem with this solution is that the active state on the list items within the...

I see. ๐Ÿ˜‰ transition:persist copies the same element around across navigation and so you lose updates.

So next try:
Removetransition:persist="scrolled-list" from EventsColumn.astro:97
and instead set id="scrolled-list" on the outer most div in EventsList.astro (line 22)

Then add this script to the end of [...slug].astro:

<script>
  document.addEventListener("astro:before-swap", (event) => {
    const originalSwap = event.swap;
    event.swap = () => {
      const scrollTop = document.getElementById("scrolled-list")?.scrollTop || 0;
      originalSwap();
      const updatedList = document.getElementById("scrolled-list");
      updatedList && (updatedList.scrollTop = scrollTop);
    };
  });
</script>

This should copy the scroll position of the list before the navigation to the corresponding and probably updated list in the new page after the swap.
Once loaded, the script runs on every navigation. Therefore the code has to take into account that some pages do not have #scrolled-list.
If you walk away from [...slug] to a page without #scrolled-list and then return, you will see the top of the list again.
You could alternatively persist the scrollTop value in sessionStorage or even localStorage to never lose it ๐Ÿ˜‰

covert latch