Skip to content

Commit e48488d

Browse files
authored
Add static search (#1049)
integrates Pagefind - https://pagefind.app to enable static search functionality. Pagefind provides client-side search indexing, improving site search performance without requiring a backend service.
1 parent 2cc55e4 commit e48488d

File tree

5 files changed

+224
-1
lines changed

5 files changed

+224
-1
lines changed

Diff for: astro.config.mjs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import remarkToc from "remark-toc";
88
import rehypeSlug from "rehype-slug";
99
import rehypeAutolinkHeadings from "rehype-autolink-headings";
1010
import metaTags from "astro-meta-tags";
11+
import pagefind from "astro-pagefind";
1112

1213
// https://astro.build/config
1314
export default defineConfig({
@@ -42,6 +43,7 @@ export default defineConfig({
4243
nesting: true,
4344
}),
4445
metaTags(),
46+
pagefind(),
4547
],
4648
output: "static",
4749
});

Diff for: package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"scripts": {
66
"dev": "astro dev",
77
"start": "astro dev",
8-
"build": "astro check && astro build",
8+
"build": "astro check && astro build && pnpm pagefind --site dist",
99
"preview": "astro preview",
1010
"astro": "astro",
1111
"format": "prettier --write --plugin=prettier-plugin-astro ."
@@ -23,6 +23,7 @@
2323
"@types/react-dom": "^19.0.4",
2424
"astro": "^5.1.6",
2525
"astro-meta-tags": "^0.3.1",
26+
"astro-pagefind": "^1.8.1",
2627
"clsx": "^2.1.1",
2728
"date-fns": "^4.1.0",
2829
"date-fns-tz": "^3.2.0",

Diff for: pagefind.yml

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
site: dist
2+
glob: "**/*.{html}"

Diff for: pnpm-lock.yaml

+93
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: src/components/header/header-actions.astro

+125
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
import ButtonLink from "../button-link/button-link.astro";
33
import HeaderButton from "./header-button.astro";
4+
import Search from "astro-pagefind/components/Search";
45
56
export interface Props {
67
mobile?: boolean;
@@ -12,6 +13,13 @@ const IS_LIVE = false;
1213
---
1314

1415
<div class="ml-auto flex items-center space-x-4">
16+
<Search id="search" className="pagefind-ui" uiOptions={{
17+
18+
showImages: false,
19+
translations: {
20+
zero_results: "Couldn't find [SEARCH_TERM]"
21+
}
22+
}} />
1523
{
1624
!mobile ? (
1725
<>
@@ -40,3 +48,120 @@ const IS_LIVE = false;
4048
</HeaderButton>
4149
</label>
4250
</div>
51+
<script>
52+
document.addEventListener("DOMContentLoaded", function () {
53+
const searchContainer = document.querySelector(".pagefind-ui");
54+
const searchClear = document.querySelector(".pagefind-ui__search-clear");
55+
const searchInput = searchContainer?.querySelector("input");
56+
let selectedIndex = -1;
57+
58+
function updateSelection() {
59+
const results = searchContainer?.querySelectorAll(".pagefind-ui__result");
60+
if (!results) return;
61+
62+
results.forEach((result, index) => {
63+
if (index === selectedIndex) {
64+
result.classList.add("selected");
65+
result.scrollIntoView({ block: "nearest", behavior: "smooth" });
66+
} else {
67+
result.classList.remove("selected");
68+
}
69+
});
70+
}
71+
72+
document.addEventListener("keydown", function (event) {
73+
if (!searchContainer || !searchInput) return;
74+
75+
const results = searchContainer.querySelectorAll(".pagefind-ui__result");
76+
if (document.activeElement === searchInput) {
77+
if (event.key === "ArrowDown") {
78+
event.preventDefault();
79+
selectedIndex = (selectedIndex + 1) % results.length;
80+
updateSelection();
81+
} else if (event.key === "ArrowUp") {
82+
event.preventDefault();
83+
selectedIndex = (selectedIndex - 1 + results.length) % results.length;
84+
updateSelection();
85+
} else if (event.key === "Enter" && selectedIndex >= 0) {
86+
event.preventDefault();
87+
results[selectedIndex].querySelector("a")?.click();
88+
}
89+
}
90+
});
91+
92+
// Reset selection when the search query changes
93+
searchInput?.addEventListener("input", function () {
94+
selectedIndex = -1;
95+
});
96+
97+
});
98+
</script>
99+
<style is:global>
100+
.pagefind-ui__result.selected {
101+
background-color: #f5f5f5;
102+
background-image: linear-gradient(to right, #3684B6 7px, transparent 5px);
103+
-webkit-transform: translate3d(0, 0, 0);
104+
transform: translate3d(0, 0, 0);
105+
}
106+
.pagefind-ui__drawer {
107+
}
108+
.pagefind-ui__message {
109+
margin: 1em;
110+
}
111+
.pagefind-ui__result mark {
112+
background: #F9EB5D;
113+
background-image: linear-gradient(to right, #F9EB5D 10%, #FCF4A7 100%);
114+
margin: 4px;
115+
padding-right: 6px;
116+
padding-left: 6px;
117+
padding-top: 2px;
118+
padding-bottom: 2px;
119+
color: #000000;
120+
font-family: monospace;
121+
border-radius: 4px;
122+
}
123+
.pagefind-ui {
124+
--pagefind-ui-scale: 1;
125+
--pagefind-ui-primary: #141f36;
126+
--pagefind-ui-text: black;
127+
--pagefind-ui-border: #d8d8d8;
128+
--pagefind-ui-border-width: 2px;
129+
--pagefind-ui-border-radius: 0;
130+
width: 50%;
131+
}
132+
.pagefind-ui.yellow {
133+
--pagefind-ui-background: #efc302;
134+
}
135+
.pagefind-ui.red {
136+
--pagefind-ui-background: #ffb9bb;
137+
width: 50%;
138+
}
139+
.pagefind-ui .pagefind-ui__drawer:not(.pagefind-ui__hidden) {
140+
position: absolute;
141+
left: auto;
142+
right: 0;
143+
margin-top: 0px;
144+
width:50vw;
145+
z-index: 9999;
146+
overflow-y: auto;
147+
box-shadow: 0 10px 10px -5px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.1);
148+
border-bottom-right-radius: var(--pagefind-ui-border-radius);
149+
border-bottom-left-radius: var(--pagefind-ui-border-radius);
150+
background-color: var(--pagefind-ui-background);
151+
}
152+
.pagefind-ui__result{
153+
padding: 0 2em 1em !important;
154+
}
155+
.pagefind-ui .pagefind-ui__result-link {
156+
color: var(--pagefind-ui-primary);
157+
}
158+
.pagefind-ui .pagefind-ui__result-excerpt {
159+
color: var(--pagefind-ui-text);
160+
}
161+
@media (max-width: 1280px) {
162+
.pagefind-ui {
163+
display:none;
164+
}
165+
}
166+
167+
</style>

0 commit comments

Comments
 (0)