Using viewtransition for dark mode in astro – Astro

by
Maya Patel
astro astrojs html view-transitions-api

Quick Fix: Within the switchTheme function, inspect if themeToggle is checked, Assign ‘dark’ attribute value to the ‘data-theme’ attribute of the document root element if checked. Finally, store ‘dark’ in ‘localStorage’ with key ‘theme’.

The Problem:

The user is implementing dark mode in their Astro project using a custom checkbox. The dark mode toggle works as expected when interacting with the checkbox, but the issue arises when navigating between routes using Astro’s view transitions. The local storage is not persisting the dark mode preference, causing the theme to reset to the default state on each route change, even though the checkbox remains checked. The user suspects this behavior is due to their implementation of the checkbox’s change event listener and the event listener used for handling Astro’s view transitions.

The Solutions:

Solution 2: Utilize `transition:persist` for State Persistence

To resolve the issue with dark mode persistency across route changes, you need to implement the transition:persist attribute within the HTML element of your Astro project. This attribute instructs Astro to maintain the state of specific elements during transitions.

Follow these steps to implement transition:persist:

  1. Add the transition:persist Attribute:

    Within your main HTML file, usually index.astro, locate the root element, typically the <html> or <body> element. Add the transition:persist attribute to this element.

    For example, if you’re using <html> as your root element, it might look like this:

    <html transition:persist>
    <!-- Your HTML content -->
    </html>
    
  2. Update the Dark Mode Event Listener:

    Modify the JavaScript code that handles the dark mode toggle to utilize the astro:route-change event instead of astro:after-swap. The astro:route-change event is triggered before a route change occurs, allowing you to persist the dark mode state before the transition.

    Here’s an example of the updated event listener:

    document.addEventListener("astro:route-change", (e) => {
      // Check if the theme is set to "dark" in local storage
      const currentTheme = localStorage.getItem("theme");
      if (currentTheme === "dark") {
        // Set the body data-theme attribute to "dark"
        document.documentElement.setAttribute("data-theme", "dark");
    
        // Check the theme toggle checkbox
        const themeToggle = document.querySelector('.theme-switch input[type="checkbox"]');
        themeToggle.checked = true;
      }
    });
    

With these changes, the dark mode state will be preserved across route changes. When a route change occurs, Astro will persist the state of the theme toggle checkbox and the data-theme attribute on the <html> or <body> element. This way, the dark mode setting remains intact even after navigating to different pages within your Astro application.

Q&A

What is the reason dark mode does not persist when changing routes?

The event listener used to switch themes is not triggered when the checkbox is changed.

How to fix the dark mode persistence issue?

Use the transition:persist attribute on the html element to tell Astro to persist state between transitions.

Is there a video tutorial that explains how to implement dark mode with view transitions in Astro?

Yes, there is a video tutorial available at https://youtu.be/9T4N0cIlBUE?feature=shared&t=287.

Video Explanation:

The following video, titled "Astro View Transitions (3.0 Release!) - YouTube", provides additional insights and in-depth exploration related to the topics discussed in this post.

Play video

... Theme: https://marketplace.visualstudio.com/items?itemName ... In this video, we'll talk through the View Transitions feature in Astro 3.0.