1
0
Fork 0

feat(docsearch): add search suggestions

This commit is contained in:
François Chalifour 2020-04-01 15:34:14 +02:00
parent fa42ab2bd9
commit a448e9ee72
4 changed files with 87 additions and 7 deletions

View file

@ -51,6 +51,8 @@ export function DocSearch({
getInputProps,
getMenuProps,
getItemProps,
setQuery,
refresh,
} = React.useMemo(
() =>
createAutocomplete<
@ -66,7 +68,7 @@ export function DocSearch({
onStateChange({ state }) {
setState(state as any);
},
getSources({ query }) {
getSources({ query, state, setContext }) {
return getAlgoliaHits({
searchClient,
queries: [
@ -117,6 +119,14 @@ export function DocSearch({
});
const sources = groupBy(formattedHits, hit => hit.hierarchy.lvl0);
// We store the `lvl0`s to display them as search suggestions
// in the “no results“ screen.
if (state.context.searchSuggestions === undefined) {
setContext({
searchSuggestions: Object.keys(sources),
});
}
return Object.values<DocSearchHit[]>(sources).map(items => {
return {
onSelect() {
@ -220,9 +230,12 @@ export function DocSearch({
<div className="DocSearch-Dropdown" ref={dropdownRef}>
<Dropdown
inputRef={inputRef}
state={state}
getMenuProps={getMenuProps}
getItemProps={getItemProps}
setQuery={setQuery}
refresh={refresh}
/>
</div>

View file

@ -14,6 +14,9 @@ interface DropdownProps {
state: AutocompleteState<InternalDocSearchHit>;
getMenuProps: GetMenuProps;
getItemProps: GetItemProps<InternalDocSearchHit, React.MouseEvent>;
setQuery(value: string): void;
refresh(): Promise<void>;
inputRef: React.MutableRefObject<HTMLInputElement>;
}
export function Dropdown(props: DropdownProps) {
@ -25,7 +28,14 @@ export function Dropdown(props: DropdownProps) {
props.state.status === 'idle' &&
props.state.suggestions.every(source => source.items.length === 0)
) {
return <NoResults query={props.state.query} />;
return (
<NoResults
setQuery={props.setQuery}
refresh={props.refresh}
state={props.state}
inputRef={props.inputRef}
/>
);
}
return (

View file

@ -1,12 +1,58 @@
import React from 'react';
import { AutocompleteState } from '@francoischalifour/autocomplete-core';
interface NoResultsProps {
query: string;
state: AutocompleteState<any>;
setQuery(value: string): void;
refresh(): Promise<void>;
inputRef: React.MutableRefObject<HTMLInputElement>;
}
export function NoResults(props: NoResultsProps) {
return <div className="DocSearch-NoResults">
<div className="Docsearch-Hit-title">No results for {props.query}.</div>
<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>
</div>;
return (
<div className="DocSearch-NoResults">
<p className="Docsearch-Hit-title">
No results for {props.state.query}.
</p>
<p>
Try searching for{' '}
{(props.state.context.searchSuggestions as string[])
.slice(0, 3)
.reduce<React.ReactNode[]>(
(acc, search) => [
...acc,
acc.length > 0 ? ', ' : '',
'“',
<button
className="DocSearch-Link"
key={search}
onClick={() => {
props.setQuery(search.toLowerCase() + ' ');
props.refresh();
props.inputRef.current.focus();
}}
>
{search}
</button>,
'“',
],
[]
)}
.
</p>
<p className="DocSearch-Label">
If you believe this query should return results, please{' '}
<a
href="https://github.com/algolia/docsearch-configs/issues/new?template=Missing_results.md"
target="_blank"
rel="noopener noreferrer"
>
let us know on GitHub
</a>
.
</p>
</div>
);
}

View file

@ -169,6 +169,17 @@ html[data-theme='dark'] {
text-decoration: none;
}
.DocSearch-Link {
appearance: none;
background: none;
border: none;
color: var(--docsearch-highlight-color);
cursor: pointer;
font: inherit;
margin: 0;
padding: 0;
}
.DocSearch-Modal {
position: relative;
flex-direction: column;