Skip to content

Commit 4b87f3e

Browse files
committed
Fix pagefind
1 parent 0269b1f commit 4b87f3e

1 file changed

Lines changed: 58 additions & 41 deletions

File tree

src/components/SearchBar.astro

Lines changed: 58 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,20 @@ const ui = uiStrings(locale.code);
1111
---
1212

1313
{/*
14-
Pagefind UI mounts inside #search and is initialized once the script
15-
loads. The stylesheet is also produced by `pagefind` at build time, so
16-
in dev (where pagefind hasn't run yet) both URLs 404 silently and the
17-
search bar is inert — the rest of the page renders fine.
14+
Pagefind ships its own search UI as a self-contained module. We just
15+
give it a mount point, mount once, and let it draw the input and the
16+
result list itself. The wrapper is `position: relative` so the result
17+
list can be positioned as a floating dropdown that doesn't expand the
18+
sticky header when the user types.
19+
20+
In dev mode pagefind hasn't run yet, so /pagefind/* 404s and the
21+
search box is silently inert — the rest of the page is unaffected.
1822
*/}
1923
<link rel="stylesheet" href="/pagefind/pagefind-ui.css" />
2024

21-
<div
22-
id="search"
23-
data-pagefind-search
24-
class="hidden md:block w-72 lg:w-80"
25-
></div>
25+
<div class="search-shell relative hidden md:block">
26+
<div id="search" class="w-56 lg:w-64"></div>
27+
</div>
2628

2729
<script src="/pagefind/pagefind-ui.js" is:inline defer></script>
2830
<script
@@ -34,32 +36,33 @@ const ui = uiStrings(locale.code);
3436
languageCode: locale.code,
3537
}}
3638
>
37-
// Pagefind UI is a UMD bundle that exposes `window.PagefindUI`. We can
38-
// safely re-use the same #search element across navigations because we
39-
// only mount once per page load.
39+
// pagefind-ui.js is loaded with `defer`, so per the HTML spec it has
40+
// executed by the time DOMContentLoaded fires. We mount exactly once
41+
// to avoid stacking duplicate widgets on the same element.
42+
let mounted = false;
4043
function mountPagefind() {
44+
if (mounted) return;
4145
if (typeof window.PagefindUI !== 'function') return;
46+
mounted = true;
4247
new window.PagefindUI({
4348
element: '#search',
4449
showImages: false,
4550
showSubResults: true,
46-
resetStyles: false,
4751
placeholder,
4852
translations: {
4953
placeholder,
5054
clear_search: clearLabel,
5155
zero_results: zeroResults,
5256
},
53-
// Restrict results to the current page locale so visitors browsing
54-
// the German site don't get Spanish hits.
55-
mergeIndex: [],
57+
// Restrict to the current page's language so a German page doesn't
58+
// surface Spanish hits.
5659
processResult: (result) => {
60+
const lang = result && result.meta && result.meta.language;
5761
if (
5862
languageCode &&
59-
result.meta &&
60-
result.meta.language &&
61-
result.meta.language !== languageCode &&
62-
!result.meta.language.startsWith(languageCode.split('-')[0])
63+
lang &&
64+
lang !== languageCode &&
65+
lang.split('-')[0] !== languageCode.split('-')[0]
6366
) {
6467
return null;
6568
}
@@ -68,46 +71,60 @@ const ui = uiStrings(locale.code);
6871
});
6972
}
7073
if (document.readyState === 'loading') {
71-
document.addEventListener('DOMContentLoaded', mountPagefind);
74+
document.addEventListener('DOMContentLoaded', mountPagefind, { once: true });
7275
} else {
7376
mountPagefind();
7477
}
75-
// pagefind-ui.js is loaded with `defer`, so it may not be ready by the
76-
// time the listener above fires — also try once it's actually present.
77-
window.addEventListener('load', mountPagefind);
7878
</script>
7979

8080
<style is:global>
81-
/* Make Pagefind's default UI inherit the site's accent and surface
82-
colours so the search box visually belongs to the header. */
83-
#search {
81+
/*
82+
* Map Pagefind's CSS custom properties to the template's theme tokens
83+
* so the search input visually belongs to the header.
84+
*/
85+
.search-shell {
8486
--pagefind-ui-primary: var(--color-accent, var(--accent, #3b82f6));
8587
--pagefind-ui-text: var(--color-text);
8688
--pagefind-ui-background: var(--color-surface);
8789
--pagefind-ui-border: var(--color-border);
8890
--pagefind-ui-tag: var(--color-surface-2);
8991
--pagefind-ui-border-width: 1px;
90-
--pagefind-ui-border-radius: 9999px;
92+
--pagefind-ui-border-radius: 0.5rem;
9193
--pagefind-ui-font: inherit;
9294
}
93-
#search .pagefind-ui__search-input {
94-
height: 2.25rem;
95-
padding-inline: 0.875rem 2.25rem;
96-
font-size: 0.875rem;
97-
}
98-
/* The drawer with results: anchor it to the input and lift it above the
99-
sticky header so it isn't clipped by the header's bottom border. */
100-
#search .pagefind-ui__drawer {
95+
96+
/*
97+
* The result list is rendered inline below the input by default. Lift
98+
* it out of the document flow so that typing doesn't shove the rest
99+
* of the header content downward, and clamp its width so it doesn't
100+
* overflow the viewport's right edge.
101+
*/
102+
.search-shell .pagefind-ui__drawer {
101103
position: absolute;
102-
inset-inline-end: 0;
103104
top: calc(100% + 0.5rem);
104-
width: min(28rem, 90vw);
105-
max-height: 70vh;
105+
inset-inline-end: 0;
106+
width: min(28rem, calc(100vw - 2rem));
107+
max-height: min(70vh, 32rem);
106108
overflow: auto;
107-
border-radius: 1rem;
108-
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.18);
109+
margin: 0;
110+
padding: 0.5rem;
109111
background: var(--color-surface);
110112
border: 1px solid var(--color-border);
113+
border-radius: 0.75rem;
114+
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.18);
111115
z-index: 50;
112116
}
117+
.search-shell .pagefind-ui__drawer:empty,
118+
.search-shell .pagefind-ui__drawer.pagefind-ui__hidden {
119+
display: none;
120+
}
121+
122+
/* Tighten the input row to fit the header's vertical rhythm. */
123+
.search-shell .pagefind-ui__form {
124+
margin: 0;
125+
}
126+
.search-shell .pagefind-ui__search-input {
127+
height: 2.25rem;
128+
font-size: 0.875rem;
129+
}
113130
</style>

0 commit comments

Comments
 (0)