Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Consent not showing with Astro View Transitions #728

Closed
dontic opened this issue Sep 2, 2024 · 5 comments
Closed

[Bug]: Consent not showing with Astro View Transitions #728

dontic opened this issue Sep 2, 2024 · 5 comments
Labels
documentation Improvements or additions to documentation

Comments

@dontic
Copy link

dontic commented Sep 2, 2024

Expected Behavior

The cookie consent banner still shows when the user changes page in an Astro app that uses view transitions.

Current Behavior

The consent loads just fine the first time the site gets loaded but then just doesn't appear again after a page change in Astro when using view transitions. If view transitions is removed, the cookie consent works just fine.

Steps to reproduce

  1. Build an astro App that uses view transitions: https://docs.astro.build/en/guides/view-transitions/
  2. Implement CookeConsent following the HTML steps in: https://cookieconsent.orestbida.com/essential/getting-started.html#html
  3. Implement the astro:page-swap event listener to re-execute the script after the user navigates to another page
  4. For easiness of use, put everything into an .astro component like so:
<script type="module" is:inline>
  import "https://cdn.jsdelivr.net/gh/orestbida/[email protected]/dist/cookieconsent.umd.js";

  function initCookieConsent() {
    CookieConsent.run({
      ...
    });
  }

  // Initialize the CookieConsent script
  initCookieConsent();

  // Reinitialize the CookieConsent script after Astro navigation
  document.addEventListener("astro:after-swap", () => {
    console.log("Page swapped, re-running initCookieConsent...")
    initCookieConsent();
  });
</script>
  1. Run the app, see how the first time the site loads the cookie consent banner works just fine
  2. Then change pages and:
    a. See how the event listener triggers with a console log
    b. See how the banner doesn't come up again
  3. Comment out the view transitions component and see how the banner works just fine

Proposed fix or additional info.

Tried many ways to fix this:

  1. Removing the script and re-adding it after a page swap
  2. Removing Cookie Consent animations by modifying its CSS
  3. Using astro:page-load instead
  4. Using .js or .astro and importing the script in multiple ways, by using import, src, etc.

None of these worked.

Please note that libraries such as AOS (animate on scroll) do work just fine by following this method. See: https://webreaper.dev/posts/astro-aos-view-transitions/

So it must be some kind of incompatibility between the Cookie Consent package and Astro with view transitions.

Version

3.0.1

On which browser do you see the issue?

Microsoft Edge

@dontic dontic added the bug Something isn't working label Sep 2, 2024
@github-actions github-actions bot added the triage yet to be reviewed label Sep 2, 2024
@orestbida
Copy link
Owner

orestbida commented Sep 2, 2024

The plugin is not an Astro component so it's expected that it doesn't integrate with the View Transition API.

Astro is not aware of the html markup generated by the plugin, since it's dynamically injected on runtime.

You need to somehow make the generated html and event listeners persist across pages. The plugin sets its classes on the top html tag, which unfortunately is refreshed on page change, so we also need to persist the className attribute of the html tag.

This is how I would do it;

  1. Create a main/base astro layout which all pages should inherit. Load the plugin in the base layout, so that it's always in a specific fixed position, and also so that it's a common element in all the pages.
  2. Create a special persistent container in the base layout, so that Astro doesn't reload it, for example:
<div transition:persist id="cc-container"> 
  ... content of plugin
</div>

The plugin will then be configured to generate the markup inside that container:

CookieConsent.run({
  root: '#cc-container',

  // ...
});
  1. Lastly, we should store the html.className attribute before the page load, and restore it before the page swap, using a little js:
document.addEventListener('astro:before-preparation', event => {
    window._htmlClassName = window.document.documentElement.className;
});

document.addEventListener('astro:before-swap', event => {
    event.newDocument.documentElement.className = window._htmlClassName;
});

Here is a quick demo on StackBlitz.

@orestbida orestbida added documentation Improvements or additions to documentation and removed bug Something isn't working triage yet to be reviewed labels Sep 2, 2024
@dontic
Copy link
Author

dontic commented Sep 3, 2024

Thanks @orestbida ! I was hitting my head against the wall at this point, turns out restoring the html.className attributes did the trick.

Thanks a lot for taking the time to show the implementation.

Edit:

Seems it's not as "simple".

2 things:

  1. Using the suggested scripts restore the full previous html class, which means that if some other class is being added on a page it won't, as the previous class will be restored on top of it. This can have a solution though, and that is to add the show--consent class only:

    <script is:inline>
        // Restore the `show--consent` class if it was present before the page swap
        document.addEventListener("astro:before-preparation", event => {
          const htmlClassName = window.document.documentElement.className;
          const consentClassPresent = htmlClassName.includes("show--consent")
            ? true
            : false;
          window._showConsentClass = consentClassPresent;
        });
    
        document.addEventListener("astro:before-swap", event => {
          const showConsent = window._showConsentClass ? ` show--consent` : "";
          event.newDocument.documentElement.className += showConsent;
        });
      </script>

    I'm unaware of other html classes that CookieConsent uses, but this one seems to do the trick just fine.

  2. Whenever you have a transition:name attribute (https://docs.astro.build/en/guides/view-transitions/#transition-directives) the suggested solution fails. I have no idea why, but even with the transition:persist element, the cookie consent banner html code completely disappears. See solution below

As a permanent solution I just went with disabling page interaction until the cookie consent is either accepted or denied by the user: https://cookieconsent.orestbida.com/reference/configuration-reference.html#disablepageinteraction

This allows you to maintain view transitions in Astro while also ensuring the consent is dealt with before the user navigates the page. It's a clean and easy solution in my opinion, without having to go through the hussle of all of this.

In any other case, @orestbida if you have any suggestion for solving the second point since I'm not that "Astro savvy" please feel free to do so for anyone who wants to implement it anyways.

@dontic dontic closed this as completed Sep 3, 2024
@orestbida
Copy link
Owner

Not sure, transition:name directives also work fine on my end, or at least with this basic demo.

@dontic
Copy link
Author

dontic commented Sep 3, 2024

Huh! Something might be going on with my implementation. I'll keep investigating and letting you know if I find what it is.

@dontic
Copy link
Author

dontic commented Sep 3, 2024

@orestbida solved! Over at the Astro Discord they helped me figure it out.

Apparently transition:persist can take transition names (see https://docs.astro.build/en/guides/view-transitions/#maintaining-state) so by providing a random string such as:

<div transition:persist="find-me-on-the-other-side" id="cc-container">

You can ensure the persist clause isn't affected by other transition names.

Not sure why your sample code worked and mine didn't, but maybe it's useful in that awesome StackBlitz of yours.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

2 participants