diff options
Diffstat (limited to 'src/components/layout')
| -rw-r--r-- | src/components/layout/Footer.astro | 27 | ||||
| -rw-r--r-- | src/components/layout/Header.astro | 118 |
2 files changed, 145 insertions, 0 deletions
diff --git a/src/components/layout/Footer.astro b/src/components/layout/Footer.astro new file mode 100644 index 0000000..5eea6e8 --- /dev/null +++ b/src/components/layout/Footer.astro @@ -0,0 +1,27 @@ +--- +import { menuLinks, siteConfig } from "@/site.config"; + +const year = new Date().getFullYear(); +--- + +<footer + class="mt-auto flex w-full flex-col items-center justify-center gap-y-2 pt-20 pb-4 text-center align-top font-semibold text-gray-600 sm:flex-row sm:justify-between sm:text-xs dark:text-gray-400" +> + <div class="me-0 sm:me-4"> + © {siteConfig.author} + {year}.<span class="inline-block"> 🚀 {siteConfig.title}</span> + </div> + <nav + aria-labelledby="footer_links" + class="flex gap-x-2 sm:gap-x-0 sm:divide-x sm:divide-gray-500" + > + <p id="footer_links" class="sr-only">More on this site</p> + { + menuLinks.map((link) => ( + <a class="hover:text-global-text px-4 py-2 hover:underline sm:py-0" href={link.path}> + {link.title} + </a> + )) + } + </nav> +</footer> diff --git a/src/components/layout/Header.astro b/src/components/layout/Header.astro new file mode 100644 index 0000000..65ea5cc --- /dev/null +++ b/src/components/layout/Header.astro @@ -0,0 +1,118 @@ +--- +import Search from "@/components/Search.astro"; +import ThemeToggle from "@/components/ThemeToggle.astro"; +import { menuLinks } from "@/site.config"; +import {siteConfig} from "../../site.config"; +--- + +<header class="group relative mb-28 flex items-center sm:ps-18" id="main-header"> + <div class="flex sm:flex-col"> + <a + aria-current={Astro.url.pathname === "/" ? "page" : false} + class="inline-flex items-center grayscale hover:filter-none sm:relative sm:inline-block" + href="/" + > + <svg + aria-hidden="true" + class="me-3 h-10 w-6 sm:absolute sm:-start-18 sm:me-0 sm:h-20 sm:w-12" + fill="none" + focusable="false" + viewBox="0 0 272 480" + xmlns="http://www.w3.org/2000/svg" + > + <title>Logo</title> + <path + d="M181.334 93.333v-40L226.667 80v40l-45.333-26.667ZM136.001 53.333 90.667 26.667v426.666L136.001 480V53.333Z" + fill="#B04304"></path> + <path + d="m136.001 119.944 45.333-26.667 45.333 26.667-45.333 26.667-45.333-26.667ZM90.667 26.667 136.001 0l45.333 26.667-45.333 26.666-45.334-26.666ZM181.334 53.277l45.333-26.666L272 53.277l-45.333 26.667-45.333-26.667ZM0 213.277l45.333-26.667 45.334 26.667-45.334 26.667L0 213.277ZM136 239.944l-45.333-26.667v53.333L136 239.944Z" + fill="#FF5D01"></path> + <path + d="m136 53.333 45.333-26.666v120L226.667 120V80L272 53.333V160l-90.667 53.333v240L136 480V306.667L45.334 360V240l45.333-26.667v53.334L136 240V53.333Z" + fill="#53C68C"></path> + <path d="M45.334 240 0 213.334v120L45.334 360V240Z" fill="#B04304"></path> + </svg> + <span class="text-xl font-bold sm:text-2xl">{siteConfig.title}</span> + </a> + <nav + aria-label="Main menu" + class="bg-global-bg/85 text-accent sm:divide-accent absolute -inset-x-4 top-14 hidden flex-col items-end gap-y-4 rounded-md py-4 shadow backdrop-blur-sm group-[.menu-open]:z-50 group-[.menu-open]:flex sm:static sm:z-auto sm:-ms-4 sm:mt-1 sm:flex sm:flex-row sm:items-center sm:divide-x sm:rounded-none sm:bg-transparent sm:py-0 sm:shadow-none sm:backdrop-blur-none" + id="navigation-menu" + > + { + menuLinks.map((link) => ( + <a + aria-current={Astro.url.pathname === link.path ? "page" : false} + class="px-4 py-4 underline-offset-2 hover:underline sm:py-0" + data-astro-prefetch + href={link.path} + > + {link.title} + </a> + )) + } + </nav> + </div> + <Search /> + <ThemeToggle /> + <mobile-button> + <button + aria-expanded="false" + aria-haspopup="menu" + class="group relative ms-4 h-7 w-7 sm:invisible sm:hidden" + id="toggle-navigation-menu" + type="button" + > + <span class="sr-only">Open main menu</span> + <svg + aria-hidden="true" + class="absolute start-1/2 top-1/2 h-full w-full -translate-x-1/2 -translate-y-1/2 transition-all group-aria-expanded:scale-0 group-aria-expanded:opacity-0" + fill="none" + focusable="false" + id="line-svg" + stroke="currentColor" + stroke-width="1.5" + viewBox="0 0 24 24" + xmlns="http://www.w3.org/2000/svg" + > + <path d="M3.75 9h16.5m-16.5 6.75h16.5" stroke-linecap="round" stroke-linejoin="round" + ></path> + </svg> + <svg + aria-hidden="true" + class="text-accent absolute start-1/2 top-1/2 h-full w-full -translate-x-1/2 -translate-y-1/2 scale-0 opacity-0 transition-all group-aria-expanded:scale-100 group-aria-expanded:opacity-100" + class="text-accent" + fill="none" + focusable="false" + id="cross-svg" + stroke="currentColor" + stroke-width="1.5" + viewBox="0 0 24 24" + xmlns="http://www.w3.org/2000/svg" + > + <path d="M6 18L18 6M6 6l12 12" stroke-linecap="round" stroke-linejoin="round"></path> + </svg> + </button> + </mobile-button> +</header> + +<script> + import { toggleClass } from "@/utils/domElement"; + + class MobileNavBtn extends HTMLElement { + #menuOpen: boolean = false; + + connectedCallback() { + const headerEl = document.getElementById("main-header")!; + const mobileButtonEl = this.querySelector<HTMLButtonElement>("button"); + + mobileButtonEl?.addEventListener("click", () => { + if (headerEl) toggleClass(headerEl, "menu-open"); + this.#menuOpen = !this.#menuOpen; + mobileButtonEl.setAttribute("aria-expanded", this.#menuOpen.toString()); + }); + } + } + + customElements.define("mobile-button", MobileNavBtn); +</script> |
