Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions src/components/BaseHead.astro
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
---
// Import the global.css file here so that it is included on
// all pages through the use of the <BaseHead /> component.
import "../styles/global.css";
import "@fontsource-variable/inter";

interface Props {
title: string;
Expand Down Expand Up @@ -61,5 +57,5 @@ const { title, description, image = "/social-card.png" } = Astro.props;

<script
is:inline
src="https://kit.fontawesome.com/14a4971ab3.js"
src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/js/all.min.js"
crossorigin="anonymous"></script>
2 changes: 2 additions & 0 deletions src/components/footer.astro → src/components/Footer.astro
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const buildTimestamp = import.meta.env.TIMESTAMP;
const gitVersion = import.meta.env.GIT_VERSION;
---

<div class="mt-auto">
<Fullbleed className="bg-primary text-white">
<footer
class="max-w-4xl lg:max-w-6xl mx-auto py-16 lg:grid grid-cols-2 px-6 gap-60"
Expand Down Expand Up @@ -106,3 +107,4 @@ const gitVersion = import.meta.env.GIT_VERSION;
</article>
</footer>
</Fullbleed>
</div>
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
---
import { promises as fs } from "fs";
import { NavItems } from "../nav-items";
import HeaderActions from "./header-actions.astro";
import HeaderLogo from "./header-logo.astro";
import { NavItems } from "@components/nav-items";
import HeaderActions from "@components/header/header-actions.astro";
import HeaderLogo from "@components/header/header-logo.astro";

const links = JSON.parse(await fs.readFile("./src/data/links.json", "utf-8"));
import links from "../data/links.json";
---

<header class="p-6 flex items-center justify-between relative z-40">
Expand All @@ -27,7 +27,7 @@ const links = JSON.parse(await fs.readFile("./src/data/links.json", "utf-8"));
<div
class="fixed bg-body-background top-0 left-0 w-screen h-screen overflow-scroll hidden peer-checked:block xl:peer-checked:hidden z-50 p-6"
>
<div class="flex items-center">
<div class="flex items-center justify-between">
<HeaderLogo />
<HeaderActions mobile />
</div>
Expand Down
154 changes: 154 additions & 0 deletions src/components/Search.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
---
import SearchComponent from "astro-pagefind/components/Search";
import Button from "@ui/Button.astro";

---

<div class="search-wrapper hidden" style="display: none;">

<div class="search-header flex items-center justify-between z-40 h-0 md:h-[85px] m-auto ">
<h2 class="text-black text-4xl ml-10 top-[46px] md:top-[85px]">Search<h2/>
<Button
id="search-close"
clear
icon="close"
iconSize="fa-xl"
class="w-[3em] h-[3em] top-[46px] md:top-[85px]"
/>
</div>
<div class="modal__overlay"></div>

<SearchComponent
id="search"
className="pagefind-ui"
uiOptions={{
showImages: false,
translations: {
zero_results: "Couldn't find [SEARCH_TERM]",
},
}}
/>
</div>

<script>
document.addEventListener("DOMContentLoaded", function () {
const searchWrapper = document.querySelector(".search-wrapper") as HTMLElement | null;
const searchContainer = document.querySelector(".pagefind-ui") as HTMLElement | null;
const searchInput = searchContainer?.querySelector("input") as HTMLInputElement | null;
const closeButton = document.querySelector("#search-close") as HTMLElement | null;
const searchButton = document.getElementById("searchButton") as HTMLElement | null;

let selectedIndex = -1;

function openSearch() {
if (searchWrapper) {
searchWrapper.style.display = "block";
if (searchInput) {
searchInput.value = "Tips";
const inputEvent = new Event("input", { bubbles: true });
searchInput.dispatchEvent(inputEvent);
setTimeout(() => {
searchInput.value = "";
searchInput.placeholder = "Tips for You";
}, 100);
searchInput.focus();
}
}
}

function closeSearch() {
if (searchWrapper) {
searchWrapper.style.display = "none";
selectedIndex = -1;
}
}

function updateSelection() {
const results = searchContainer?.querySelectorAll(".pagefind-ui__result");
if (!results) return;

results.forEach((result, index) => {
if (result instanceof HTMLElement) {
if (index === selectedIndex) {
result.classList.add("selected");
result.scrollIntoView({ block: "nearest", behavior: "smooth" });
} else {
result.classList.remove("selected");
}
}
});
}

function makeResultsClickable() {
const results = searchContainer?.querySelectorAll(".pagefind-ui__result");
if (!results) return;

results.forEach((result) => {
const link = result.querySelector(".pagefind-ui__result-link") as HTMLAnchorElement | null;
if (link && !result.hasAttribute("data-clickable")) {
if (result instanceof HTMLElement) {
result.style.cursor = "pointer";
result.addEventListener("click", (e) => {
if (!(e.target instanceof HTMLElement) || !e.target.closest("a")) {
link.click();
}
});
result.setAttribute("data-clickable", "true");
}
}
});
}

if (searchButton && searchWrapper) {
searchButton.addEventListener("click", openSearch);
}

document.addEventListener("keydown", function (event) {
if (!searchContainer || !searchInput) return;

const results = searchContainer.querySelectorAll(".pagefind-ui__result");

if (event.ctrlKey && event.key === "k") {
event.preventDefault();
openSearch();
} else if (event.key === "Escape") {
closeSearch();
} else if (document.activeElement === searchInput) {
if (event.key === "ArrowDown") {
event.preventDefault();
selectedIndex = (selectedIndex + 1) % results.length;
updateSelection();
} else if (event.key === "ArrowUp") {
event.preventDefault();
selectedIndex = (selectedIndex - 1 + results.length) % results.length;
updateSelection();
} else if (event.key === "Enter") {
event.preventDefault();
if (results.length > 0) {
const indexToOpen = selectedIndex === -1 ? 0 : selectedIndex;
const link = results[indexToOpen]?.querySelector("a") as HTMLAnchorElement | null;
link?.click();
}
}
}
});

const resultsObserver = new MutationObserver(() => {
const results = searchContainer?.querySelectorAll(".pagefind-ui__result");
if (results && results.length > 0) {
selectedIndex = 0;
updateSelection();
makeResultsClickable();
}
});

if (searchContainer) {
resultsObserver.observe(searchContainer, {
childList: true,
subtree: true,
});
}

closeButton?.addEventListener("click", closeSearch);
});
</script>
Loading