212 lines
7.3 KiB
Text
212 lines
7.3 KiB
Text
---
|
|
//Import relevant dependencies
|
|
import ThemeIcon from "../ThemeIcon.astro";
|
|
import NavLink from "../ui/links/NavLink.astro";
|
|
import Authentication from "./Authentication.astro";
|
|
import enStrings from "@/utils/navigation.ts";
|
|
import frStrings from "@/utils/fr/navigation.ts";
|
|
import BrandLogo from "../BrandLogo.astro";
|
|
import LanguagePicker from "../ui/LanguagePicker.astro";
|
|
|
|
// Select the correct translation based on the page's lang prop:
|
|
const strings = Astro.currentLocale === "fr" ? frStrings : enStrings;
|
|
const homeUrl = Astro.currentLocale === "fr" ? "/fr" : "/";
|
|
---
|
|
|
|
<!-- Main header component -->
|
|
<header
|
|
class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm md:flex-nowrap md:justify-start"
|
|
>
|
|
<!-- Navigation container -->
|
|
<nav
|
|
class="relative mx-2 w-full rounded-[36px] border border-yellow-100/40 bg-yellow-50/60 px-4 py-3 backdrop-blur-md dark:border-neutral-700/40 dark:bg-neutral-800/80 dark:backdrop-blur-md md:flex md:items-center md:justify-between md:px-6 md:py-0 lg:px-8 xl:mx-auto"
|
|
aria-label="Global"
|
|
>
|
|
<div class="flex items-center justify-between">
|
|
<!-- Brand logo -->
|
|
<a
|
|
class="flex-none rounded-lg text-xl font-bold outline-none ring-zinc-500 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none"
|
|
href={homeUrl}
|
|
aria-label="Brand"
|
|
>
|
|
<BrandLogo class="h-auto w-24" />
|
|
</a>
|
|
<!-- Collapse toggle for smaller screens -->
|
|
<div class="ml-auto mr-5 md:hidden">
|
|
<button
|
|
type="button"
|
|
class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none"
|
|
data-hs-collapse="#navbar-collapse-with-animation"
|
|
aria-controls="navbar-collapse-with-animation"
|
|
aria-label="Toggle navigation"
|
|
>
|
|
<svg
|
|
class="h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:hidden"
|
|
width="24"
|
|
height="24"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<line x1="3" x2="21" y1="6" y2="6"></line>
|
|
<line x1="3" x2="21" y1="12" y2="12"></line>
|
|
<line x1="3" x2="21" y1="18" y2="18"></line>
|
|
</svg>
|
|
<svg
|
|
class="hidden h-[1.25rem] w-[1.25rem] flex-shrink-0 hs-collapse-open:block"
|
|
width="24"
|
|
height="24"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path d="M18 6 6 18"></path>
|
|
<path d="m6 6 12 12"></path>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<!-- ThemeIcon component specifically for smaller screens -->
|
|
<span class="inline-block md:hidden">
|
|
<ThemeIcon />
|
|
</span>
|
|
</div>
|
|
<!-- Contains navigation links -->
|
|
<div
|
|
id="navbar-collapse-with-animation"
|
|
class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block"
|
|
>
|
|
<!-- Navigation links container -->
|
|
<div
|
|
class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 lg:gap-x-7 md:gap-y-0 md:ps-7"
|
|
>
|
|
<!-- Navigation links and Authentication component -->
|
|
{strings.navBarLinks.map(link => (
|
|
<NavLink url={link.url} name={link.name} />
|
|
))}
|
|
|
|
<Authentication />
|
|
<LanguagePicker />
|
|
<!-- ThemeIcon component specifically for larger screens -->
|
|
<span class="hidden md:inline-block">
|
|
<ThemeIcon />
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
</header>
|
|
<!-- Theme Appearance script to manage light/dark modes -->
|
|
<script is:inline>
|
|
const HSThemeAppearance = {
|
|
init() {
|
|
const defaultTheme = "default";
|
|
let theme = localStorage.getItem("hs_theme") || defaultTheme;
|
|
|
|
if (document.querySelector("html").classList.contains("dark")) return;
|
|
this.setAppearance(theme);
|
|
},
|
|
_resetStylesOnLoad() {
|
|
const $resetStyles = document.createElement("style");
|
|
$resetStyles.innerText = `*{transition: unset !important;}`;
|
|
$resetStyles.setAttribute("data-hs-appearance-onload-styles", "");
|
|
document.head.appendChild($resetStyles);
|
|
return $resetStyles;
|
|
},
|
|
setAppearance(theme, saveInStore = true, dispatchEvent = true) {
|
|
const $resetStylesEl = this._resetStylesOnLoad();
|
|
|
|
if (saveInStore) {
|
|
localStorage.setItem("hs_theme", theme);
|
|
}
|
|
|
|
if (theme === "auto") {
|
|
theme = window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
? "dark"
|
|
: "default";
|
|
}
|
|
|
|
document.querySelector("html").classList.remove("dark");
|
|
document.querySelector("html").classList.remove("default");
|
|
document.querySelector("html").classList.remove("auto");
|
|
|
|
document
|
|
.querySelector("html")
|
|
.classList.add(this.getOriginalAppearance());
|
|
|
|
setTimeout(() => {
|
|
$resetStylesEl.remove();
|
|
});
|
|
|
|
if (dispatchEvent) {
|
|
window.dispatchEvent(
|
|
new CustomEvent("on-hs-appearance-change", { detail: theme }),
|
|
);
|
|
}
|
|
},
|
|
getAppearance() {
|
|
let theme = this.getOriginalAppearance();
|
|
if (theme === "auto") {
|
|
theme = window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
? "dark"
|
|
: "default";
|
|
}
|
|
return theme;
|
|
},
|
|
getOriginalAppearance() {
|
|
const defaultTheme = "default";
|
|
return localStorage.getItem("hs_theme") || defaultTheme;
|
|
},
|
|
};
|
|
HSThemeAppearance.init();
|
|
|
|
window
|
|
.matchMedia("(prefers-color-scheme: dark)")
|
|
.addEventListener("change", () => {
|
|
if (HSThemeAppearance.getOriginalAppearance() === "auto") {
|
|
HSThemeAppearance.setAppearance("auto", false);
|
|
}
|
|
});
|
|
|
|
window.addEventListener("load", () => {
|
|
const $clickableThemes = document.querySelectorAll(
|
|
"[data-hs-theme-click-value]",
|
|
);
|
|
const $switchableThemes = document.querySelectorAll(
|
|
"[data-hs-theme-switch]",
|
|
);
|
|
|
|
$clickableThemes.forEach(($item) => {
|
|
$item.addEventListener("click", () =>
|
|
HSThemeAppearance.setAppearance(
|
|
$item.getAttribute("data-hs-theme-click-value"),
|
|
true,
|
|
$item,
|
|
),
|
|
);
|
|
});
|
|
|
|
$switchableThemes.forEach(($item) => {
|
|
$item.addEventListener("change", (e) => {
|
|
HSThemeAppearance.setAppearance(e.target.checked ? "dark" : "default");
|
|
});
|
|
|
|
$item.checked = HSThemeAppearance.getAppearance() === "dark";
|
|
});
|
|
|
|
window.addEventListener("on-hs-appearance-change", (e) => {
|
|
$switchableThemes.forEach(($item) => {
|
|
$item.checked = e.detail === "dark";
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
<!--Import the necessary Collapse and Overlay plugins-->
|
|
<!--https://preline.co/plugins/html/collapse.html-->
|
|
<!--https://preline.co/plugins/html/overlay.html-->
|
|
<script is:inline src="/scripts/vendor/preline/collapse/index.js"></script>
|
|
<script is:inline src="/scripts/vendor/preline/overlay/index.js"></script>
|