Bad behavour in an Astro component

170 views Asked by At

I have an Astro static web page. One of the components is:

<nav
    class="p-5 shadow md:flex md:items-center md:justify-between fixed w-full top-0"
>
    <div class="flex justify-between items-center">
        <a href="/" class="text-2xl cursor-pointer">
            <img class="h-10 inline" src="/img/logo.png" alt="Logo Image" />
             Bookingfy</a
        >
        <span class="text-3xl cursor-pointer mx-2 md:hidden block"
            ><ion-icon name="menu"></ion-icon></span
        >
    </div>

    <ul
        class="md:flex md:items-center md:z-auto md:static absolute w-full left-0 md:w-auto md:py-0 py-4 md:pl-0 pl-7 md:opacity-100 opacity-0 top-[-400px] transition-all ease-in duration-500"
    >
        <li class="mx-4 my-6 md:my-0">
            <a
                href="/generals"
                class="text-xl hover:text-orange-300 duration-500"
                >Características</a
            >
        </li>
        <li class="mx-4 my-6 md:my-0">
            <a
                href="/pricing"
                class="text-xl hover:text-orange-300 duration-500">Precios</a
            >
        </li>
        <li class="mx-4 my-6 md:my-0">
            <a href="/about" class="text-xl hover:text-orange-300 duration-500"
                >Sobre Nosotros</a
            >
        </li>
        <li class="mx-4 my-6 md:my-0">
            <a
                href="/contact"
                class="text-xl hover:text-orange-300 duration-500">Contacto</a
            >
        </li>
    </ul>
</nav>

<style>
    nav {
        background-color: #13151a;
        z-index: 999;
    }
    ul {
        background-color: #13151a;
    }
</style>

<script>
    document.addEventListener("DOMContentLoaded", function () {
        let icon = document.querySelector("ion-icon")!;

        icon.addEventListener("click", function () {
            if (icon.getAttribute("name") === "menu") {
                icon.setAttribute("name", "close");
                document.querySelector("ul")!.classList.add("top-[80px]");
                document.querySelector("ul")!.classList.add("opacity-100");
                document.querySelector("ul")!.classList.add("z-10");
            } else {
                icon.setAttribute("name", "menu");
                document.querySelector("ul")!.classList.remove("top-[80px]");
                document.querySelector("ul")!.classList.remove("opacity-100");
            }
        });
    });
</script>

And this component is inside of a Layout called Layout.astro:

---
import Footer from "../components/Footer.astro";
import Header from "../components/Header.astro";
import "../styles/Layout.scss";
import { ViewTransitions } from "astro:transitions";

interface Props {
    title: string;
}

const { title } = Astro.props;
---

<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="description" content="Astro description" />
        <meta name="viewport" content="width=device-width" />
        <link rel="icon" type="image/svg+xml" href="/img/logo.png" />
        <meta name="generator" content={Astro.generator} />
        <title>{"Bookingfy | "+title}</title>
        <script
            type="module"
            src="https://unpkg.com/[email protected]/dist/ionicons/ionicons.esm.js"
        ></script>
        <script
            nomodule
            src="https://unpkg.com/[email protected]/dist/ionicons/ionicons.js"
        ></script>
        <ViewTransitions />
    </head>
    <body>
        <Header />
        <main>
            <slot />
        </main>
        <Footer />
    </body>
</html>

The problem is with the navbar behaviour when we are in a small screen. When previously I don't navigate for other application pages, the navbar works. However, when for example I enter at one navbar option, like 'Características', and I try to reopen the navbar, this doesn't work. The navbar doesn't show the options. I don't understand this behaviour. You can copy the code in one Astro project and execute this code for better understanding. Can someone give me some help? Thank you in advance.

1

There are 1 answers

0
KroKing On

Basically, Astro will compile your JS code inside the Header component

and it will lose its location once you move to another page

so pass a directive to the script to ensure it is is:global

will make your code globally available, which will solve the issue

this is a bit dirty solution but yeah you can do smth else like attach this script to the main layout, our but all your scripts in one file and but it in the headers

<script is:global>
    document.addEventListener("DOMContentLoaded", function () {
        let icon = document.querySelector("ion-icon")!;

        icon.addEventListener("click", function () {
            if (icon.getAttribute("name") === "menu") {
                icon.setAttribute("name", "close");
                document.querySelector("ul")!.classList.add("top-[80px]");
                document.querySelector("ul")!.classList.add("opacity-100");
                document.querySelector("ul")!.classList.add("z-10");
            } else {
                icon.setAttribute("name", "menu");
                document.querySelector("ul")!.classList.remove("top-[80px]");
                document.querySelector("ul")!.classList.remove("opacity-100");
            }
        });
    });
</script>