feat(fs.dev): Implemented search
This commit is contained in:
parent
8f165dbe6d
commit
2b021e4223
7 changed files with 99 additions and 54 deletions
|
@ -30,15 +30,15 @@ const Hits = props => {
|
|||
|
||||
const CustomHits = connectHits(Hits);
|
||||
|
||||
const Highlight = ({ highlight, attribute, hit }) => {
|
||||
const Highlight = ({ highlight, attribute, hit, snippet=false }) => {
|
||||
const parsedHit = highlight({
|
||||
highlightProperty: '_highlightResult',
|
||||
highlightProperty: snippet ? '_snippetResult' : '_highlightResult',
|
||||
attribute,
|
||||
hit,
|
||||
});
|
||||
|
||||
return parsedHit.map((part, index) => part.isHighlighted
|
||||
? <mark key={index}>{part.value}</mark>
|
||||
? <mark className="text-base-content bg-secondary-focus bg-opacity-30" key={index}>{part.value}</mark>
|
||||
: <span key={index}>{part.value}</span>
|
||||
)
|
||||
}
|
||||
|
@ -48,34 +48,42 @@ const CustomHighlight = connectHighlight(Highlight);
|
|||
const Hit = props => (
|
||||
<div
|
||||
className={`
|
||||
border-base-300
|
||||
border px-3 py-1 rounded mt-1
|
||||
lg:px-6 lg:py-3 lg:border-2 lg:mt-4 lg:rounded-lg
|
||||
hover:bg-base-100 hover:text-base-content
|
||||
px-2 py-1 ounded mt-1
|
||||
text-base text-base-content
|
||||
sm:rounded
|
||||
lg:px-4 lg:py-2
|
||||
hover:bg-secondary hover:bg-opacity-10 hover:text-base-content
|
||||
${props.index === props.active
|
||||
? 'bg-base-300 text-base-content bg-opacity-30'
|
||||
: ''
|
||||
? 'bg-secondary bg-opacity-30'
|
||||
: 'bg-base-300 bg-opacity-10'
|
||||
}
|
||||
`}
|
||||
>
|
||||
<Link href={props.hit.page}>
|
||||
<a href={props.hit.page}>
|
||||
<h4 className="text-lg lg:text-2xl">
|
||||
<a href={props.hit.page} className="flex flex-row justify-between gap-2">
|
||||
<span className="text-base sm:text-xl font-bold leading-5">
|
||||
{props.hit?._highlightResult?.title
|
||||
? <CustomHighlight hit={props.hit} attribute='title' />
|
||||
: props.hit.title
|
||||
}
|
||||
</h4>
|
||||
<p className="text-sm lg:text-lg">
|
||||
/
|
||||
<b className="font-bold px-1 lg:text-lg">
|
||||
{props.hit.page.split('/')[1]}
|
||||
</b>
|
||||
/
|
||||
{props.hit.page.split('/').slice(2).join('/')}
|
||||
</p>
|
||||
</span>
|
||||
<span className="text-xs pt-0.5 sm:text-base sm:pt-1 font-bold uppercase">{props.hit.page.split('/')[1]}</span>
|
||||
</a>
|
||||
</Link>
|
||||
{props.hit?._snippetResult?.body && (
|
||||
<Link href={props.hit.page}>
|
||||
<a href={props.hit.page} className="text-sm sm:text-base block py-1">
|
||||
<CustomHighlight hit={props.hit} attribute='body' snippet />
|
||||
</a>
|
||||
</Link>
|
||||
)}
|
||||
{props.hit?._highlightResult?.page && (
|
||||
<Link href={props.hit.page}>
|
||||
<a href={props.hit.page} className="text-xs sm:text-sm block opacity-70">
|
||||
<CustomHighlight hit={props.hit} attribute='page' />
|
||||
</a>
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
|
@ -85,7 +93,6 @@ const handleInputKeydown = (evt, setSearch, setActive, active, router) => {
|
|||
if (evt.key === 'Escape') setSearch(false)
|
||||
if (evt.key === 'ArrowDown') setActive(act => act + 1)
|
||||
if (evt.key === 'ArrowUp') setActive(act => act - 1)
|
||||
if (evt.key === 'c' && prev === 'Control') evt.target.value = ''
|
||||
if (evt.key === 'Enter') {
|
||||
// Trigger navigation
|
||||
if (evt?.target?.dataset?.links) {
|
||||
|
@ -107,20 +114,9 @@ const SearchBox = props => {
|
|||
const { currentRefinement, isSearchStalled, refine, setSearch, setActive } = props
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="py-8">
|
||||
<form noValidate action="" role="search" onSubmit={(evt) => evt.preventDefault()}>
|
||||
<div className="form-control">
|
||||
<label className="label hidden lg:block">
|
||||
<span className="label-text">
|
||||
<b> Escape</b> to exit
|
||||
<span className="px-4">|</span>
|
||||
<b> Up</b> or <b>Down</b> to select
|
||||
<span className="px-4">|</span>
|
||||
<b> Enter</b> to navigate
|
||||
<span className="px-4">|</span>
|
||||
<b> Ctrl+c</b> to clear
|
||||
</span>
|
||||
</label>
|
||||
<div className="relative">
|
||||
<input
|
||||
ref={input}
|
||||
|
@ -129,17 +125,24 @@ const SearchBox = props => {
|
|||
value={currentRefinement}
|
||||
onChange={event => refine(event.currentTarget.value)}
|
||||
onKeyDown={(evt) => handleInputKeydown(evt, setSearch, setActive, props.active, router)}
|
||||
className="input lg:input-lg input-bordered input-primary w-full pr-16"
|
||||
className="input lg:input-lg input-bordered input-neutral w-full pr-16"
|
||||
placeholder='Type to search'
|
||||
/>
|
||||
<button
|
||||
className="absolute right-0 top-0 rounded-l-none btn btn-primary lg:btn-lg"
|
||||
className="absolute right-0 top-0 rounded-l-none btn btn-neutral lg:btn-lg"
|
||||
onClick={() => props.setSearch(false)}
|
||||
>X</button>
|
||||
</div>
|
||||
<label className="label hidden sm:block">
|
||||
<div className="label-text flex flex-row gap-4 justify-between">
|
||||
<div><b> Escape</b> to exit</div>
|
||||
<div><b> Up</b> or <b>Down</b> to select</div>
|
||||
<div><b> Enter</b> to navigate</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
className="overscroll-auto overflow-y-auto"
|
||||
className="overscroll-auto overflow-y-auto mt-2"
|
||||
style={{maxHeight: 'calc(100vh - 10rem)'}}
|
||||
>
|
||||
{
|
||||
|
@ -192,14 +195,9 @@ const Search = props => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="max-w-prose m-auto">
|
||||
<h1>Search</h1>
|
||||
<InstantSearch indexName={config.algolia.index} searchClient={searchClient}>
|
||||
<div>
|
||||
<CustomSearchBox {...stateProps}/>
|
||||
</div>
|
||||
</InstantSearch>
|
||||
</div>
|
||||
<InstantSearch indexName={config.algolia.index} searchClient={searchClient}>
|
||||
<CustomSearchBox {...stateProps}/>
|
||||
</InstantSearch>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue