withastro / astro

The web framework for content-driven websites. ⭐️ Star to support our work!
https://astro.build
Other
47.24k stars 2.51k forks source link

Script navigation not adding records to Chrome's history, skips previous urls when going back #12561

Closed kolostring closed 1 day ago

kolostring commented 3 days ago

Astro Info

Astro                    v4.16.15
Node                     v20.12.2
System                   Linux (x64)
Package Manager          pnpm
Output                   static
Adapter                  none
Integrations             @astrojs/react
                         @astrojs/tailwind

If this issue only occurs in one browser, which browser is a problem?

Chrome

Describe the Bug

Im using framer motion's inView() function to make a navigation (with Astro's navigate) to another route with the component at the end of the description, nothing too fancy. The Problem is when trying to go back, the previous route is not stored on browsers history (Chrome, Firefox works just fine, don't know Safari tho).

I tried with several functions, such as link.click(), window.navigation.href = href, add eventListeners to "pop state" and "hash change" (these do nothing). Only way for making it work is by clicking the anchor tag.

This is my code:

---
import PreventScrollRestauration from "./PreventScrollRestauration.astro";

const { className, href } = Astro.props;
---

<div class={`scroll-trigger-link ${className}`}>
  <a class="hidden" href={href}>THIS SHOULD NOT BE VISIBLE</a>
  <slot />
</div>

<PreventScrollRestauration />

<script>
  import { navigate } from "astro:transitions/client";
  import { inView } from "motion";

  initEventListeners();
  document.addEventListener("astro:page-load", () => {
    initEventListeners();
  });

  function initEventListeners() {
    const linkList = document.querySelectorAll(".scroll-trigger-link");

    linkList.forEach((link) => {
      const href = link.querySelector("a")?.getAttribute("href") ?? "#";
      inView(
        link,
        () => {
          navigate(href);
        },
        {
          amount: 0.99,
        }
      );
    });
  }
</script>

What's the expected result?

Going back to previous url when pressing browser's "go back" button

Link to Minimal Reproducible Example

https://stackblitz.com/edit/withastro-astro-mgttpp?file=README.md

Participation

martrapp commented 3 days ago

Hi @kolostring, :wave: navigate() is part of Astro's View Transition support.

Please try whether adding the <ViewTransitions /> component to the <head> in your Layout.astro resolves the issue for you.

---
import {ViewTransitions} from "astro:transitions" 
---
<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width" />
        <ViewTransitions />
        <meta name="generator" content={Astro.generator} />
        <title>Astro Basics</title>
    </head>
kolostring commented 2 days ago

Thanks for answering @martrapp :). I tried using ViewTransitions and skipping them, still unsolved. As I said before the behavior is the same no matter what I use (browsers native functionality or astro specific like navigate with View Transitions), Chrome will not get new History records as long as the user doesn't click anything.

martrapp commented 2 days ago

Ah sorry, misunderstood that.

martrapp commented 2 days ago

Sorry, I'm not able to reproduce your issue with Chrome on Windows. Maybe you can find some useful hints in this issue: https://github.com/withastro/astro/issues/11919

martrapp commented 2 days ago

Ah, I just couldn't let it go: Apparently, there's a race condition. I get different results depending on how (quickly) I scroll down.

EDIT: initEventListeners() was executed twice on first page load, once explicitly and then again via the astro-page-load event thus installing the navigation code twice.

martrapp commented 1 day ago

@kolostring, I removed all Astro dependent code from you example. I used the window load event instead of astro:page-load, location.assign() instead of navigate, and replaced the scroll prevention with a scrollTo(0,0) right before the automatic navigation.

This gave me the same behavior. Like you wrote before, it seems like Chrome does handle navigation without explicit user interaction on links not the way we expect. I'm afraid I can't help you with that behavior.

I close this issue now as it does not seem to be related to Astro. If you have new insights, let's continue the discussion on existing discord thread.