Skip to content

Commit a448e9e

Browse files
feat(docsearch): add search suggestions
1 parent fa42ab2 commit a448e9e

4 files changed

Lines changed: 87 additions & 7 deletions

File tree

src/DocSearch.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ export function DocSearch({
5151
getInputProps,
5252
getMenuProps,
5353
getItemProps,
54+
setQuery,
55+
refresh,
5456
} = React.useMemo(
5557
() =>
5658
createAutocomplete<
@@ -66,7 +68,7 @@ export function DocSearch({
6668
onStateChange({ state }) {
6769
setState(state as any);
6870
},
69-
getSources({ query }) {
71+
getSources({ query, state, setContext }) {
7072
return getAlgoliaHits({
7173
searchClient,
7274
queries: [
@@ -117,6 +119,14 @@ export function DocSearch({
117119
});
118120
const sources = groupBy(formattedHits, hit => hit.hierarchy.lvl0);
119121

122+
// We store the `lvl0`s to display them as search suggestions
123+
// in the “no results“ screen.
124+
if (state.context.searchSuggestions === undefined) {
125+
setContext({
126+
searchSuggestions: Object.keys(sources),
127+
});
128+
}
129+
120130
return Object.values<DocSearchHit[]>(sources).map(items => {
121131
return {
122132
onSelect() {
@@ -220,9 +230,12 @@ export function DocSearch({
220230

221231
<div className="DocSearch-Dropdown" ref={dropdownRef}>
222232
<Dropdown
233+
inputRef={inputRef}
223234
state={state}
224235
getMenuProps={getMenuProps}
225236
getItemProps={getItemProps}
237+
setQuery={setQuery}
238+
refresh={refresh}
226239
/>
227240
</div>
228241

src/Dropdown/Dropdown.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ interface DropdownProps {
1414
state: AutocompleteState<InternalDocSearchHit>;
1515
getMenuProps: GetMenuProps;
1616
getItemProps: GetItemProps<InternalDocSearchHit, React.MouseEvent>;
17+
setQuery(value: string): void;
18+
refresh(): Promise<void>;
19+
inputRef: React.MutableRefObject<HTMLInputElement>;
1720
}
1821

1922
export function Dropdown(props: DropdownProps) {
@@ -25,7 +28,14 @@ export function Dropdown(props: DropdownProps) {
2528
props.state.status === 'idle' &&
2629
props.state.suggestions.every(source => source.items.length === 0)
2730
) {
28-
return <NoResults query={props.state.query} />;
31+
return (
32+
<NoResults
33+
setQuery={props.setQuery}
34+
refresh={props.refresh}
35+
state={props.state}
36+
inputRef={props.inputRef}
37+
/>
38+
);
2939
}
3040

3141
return (

src/NoResults/NoResults.tsx

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,58 @@
11
import React from 'react';
2+
import { AutocompleteState } from '@francoischalifour/autocomplete-core';
23

34
interface NoResultsProps {
4-
query: string;
5+
state: AutocompleteState<any>;
6+
setQuery(value: string): void;
7+
refresh(): Promise<void>;
8+
inputRef: React.MutableRefObject<HTMLInputElement>;
59
}
610

711
export function NoResults(props: NoResultsProps) {
8-
return <div className="DocSearch-NoResults">
9-
<div className="Docsearch-Hit-title">No results for “{props.query}“.</div>
10-
<div className="DocSearch-Label">Try another search or if you believe this query should lead to actual results, please let us know with a <a href="">GitHub issue</a>.</div>
11-
</div>;
12+
return (
13+
<div className="DocSearch-NoResults">
14+
<p className="Docsearch-Hit-title">
15+
No results for “{props.state.query}“.
16+
</p>
17+
18+
<p>
19+
Try searching for{' '}
20+
{(props.state.context.searchSuggestions as string[])
21+
.slice(0, 3)
22+
.reduce<React.ReactNode[]>(
23+
(acc, search) => [
24+
...acc,
25+
acc.length > 0 ? ', ' : '',
26+
'“',
27+
<button
28+
className="DocSearch-Link"
29+
key={search}
30+
onClick={() => {
31+
props.setQuery(search.toLowerCase() + ' ');
32+
props.refresh();
33+
props.inputRef.current.focus();
34+
}}
35+
>
36+
{search}
37+
</button>,
38+
'“',
39+
],
40+
[]
41+
)}
42+
.
43+
</p>
44+
45+
<p className="DocSearch-Label">
46+
If you believe this query should return results, please{' '}
47+
<a
48+
href="https://github.com/algolia/docsearch-configs/issues/new?template=Missing_results.md"
49+
target="_blank"
50+
rel="noopener noreferrer"
51+
>
52+
let us know on GitHub
53+
</a>
54+
.
55+
</p>
56+
</div>
57+
);
1258
}

src/style.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,17 @@ html[data-theme='dark'] {
169169
text-decoration: none;
170170
}
171171

172+
.DocSearch-Link {
173+
appearance: none;
174+
background: none;
175+
border: none;
176+
color: var(--docsearch-highlight-color);
177+
cursor: pointer;
178+
font: inherit;
179+
margin: 0;
180+
padding: 0;
181+
}
182+
172183
.DocSearch-Modal {
173184
position: relative;
174185
flex-direction: column;

0 commit comments

Comments
 (0)