Skip to content

Commit f10f462

Browse files
authored
fix: make documentation search usable
Fixes #8
1 parent 6ead7b4 commit f10f462

1 file changed

Lines changed: 40 additions & 12 deletions

File tree

src/pages/docs/search.tsx

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,54 @@ export function DocsSearch() {
1010
const [query, setQuery] = state('');
1111
const [loading, setLoading] = state(false);
1212
const [results, setResults] = state<readonly DocsSearchRecord[]>([]);
13+
const [error, setError] = state(false);
14+
let searchGeneration = 0;
15+
16+
const focusInput = (element: HTMLElement | null) => {
17+
window.setTimeout(
18+
() =>
19+
element
20+
?.querySelector<HTMLInputElement>('[data-docs-search-input]')
21+
?.focus(),
22+
0
23+
);
24+
};
25+
26+
const openSearch = (element?: HTMLElement | null) => {
27+
setOpen(true);
28+
focusInput(element ?? null);
29+
};
1330

1431
const runSearch = async (value: string) => {
32+
const generation = ++searchGeneration;
1533
setQuery(value);
34+
setError(false);
1635
if (!value.trim()) {
1736
setResults([]);
37+
setLoading(false);
1838
return;
1939
}
2040
setLoading(true);
21-
const { searchDocs } = await import('./search-index');
22-
setResults(searchDocs(value));
23-
setLoading(false);
41+
try {
42+
const { searchDocs } = await import('./search-index');
43+
if (generation !== searchGeneration) return;
44+
setResults(searchDocs(value));
45+
} catch {
46+
if (generation !== searchGeneration) return;
47+
setResults([]);
48+
setError(true);
49+
} finally {
50+
if (generation === searchGeneration) setLoading(false);
51+
}
2452
};
2553

2654
const close = () => {
55+
searchGeneration += 1;
2756
setOpen(false);
2857
setQuery('');
2958
setResults([]);
59+
setLoading(false);
60+
setError(false);
3061
};
3162
return (
3263
<div
@@ -44,14 +75,7 @@ export function DocsSearch() {
4475
))
4576
) {
4677
event.preventDefault();
47-
setOpen(true);
48-
window.setTimeout(
49-
() =>
50-
element
51-
.querySelector<HTMLInputElement>('[data-docs-search-input]')
52-
?.focus(),
53-
0
54-
);
78+
openSearch(element);
5579
}
5680
if (event.key === 'Escape' && open()) close();
5781
});
@@ -60,7 +84,9 @@ export function DocsSearch() {
6084
<button
6185
class="docs-search__trigger"
6286
type="button"
63-
onClick={() => setOpen(true)}
87+
onClick={(event: Event) =>
88+
openSearch((event.currentTarget as HTMLElement).parentElement)
89+
}
6490
aria-haspopup="dialog"
6591
>
6692
<SearchIcon size={16} aria-hidden="true" />
@@ -106,6 +132,8 @@ export function DocsSearch() {
106132
Search page titles, component aliases, package imports, CLI
107133
commands, and every published API symbol.
108134
</p>
135+
) : error() ? (
136+
<p>Search is temporarily unavailable. Please try again.</p>
109137
) : results().length ? (
110138
<ul>
111139
{results().map((result) => (

0 commit comments

Comments
 (0)