Files
protocol/packages/website/ts/components/docs/search/autocomplete.tsx
2019-08-23 23:56:17 +02:00

291 lines
7.2 KiB
TypeScript

import React, { useState } from 'react';
import styled from 'styled-components';
import Autosuggest from 'react-autosuggest';
import { Highlight, Snippet } from 'react-instantsearch-dom';
import { colors } from 'ts/style/colors';
interface Props {
isHome?: boolean;
}
interface AutoCompleteProps {
isHome?: boolean;
hits?: object[];
currentRefinement?: string;
refine?: (value: string) => void;
}
interface HitProps {
[key: string]: any;
}
export const CustomAutoComplete: React.FC<AutoCompleteProps> = ({
isHome = false,
hits = [],
currentRefinement = '',
refine,
}) => {
const [value, setValue] = useState<string>('');
const onChange = (event: HitProps, { newValue }: HitProps): void => setValue(newValue);
const onSuggestionsFetchRequested = ({ value: newValue }: HitProps): void => refine(newValue);
const onSuggestionsClearRequested = (): void => refine('');
// tslint:disable-next-line: no-empty
const onSuggestionHighlighted = (): void => {};
const getSuggestionValue = (hit: HitProps): string => hit.textContent;
const onSuggestionSelected = (event: HitProps, { suggestion }: HitProps): void => {
// tslint:disable-next-line: no-console
console.log(suggestion);
};
const renderSuggestion = (hit: HitProps): React.ReactNode => {
return (
<>
<Highlight attribute="title" hit={hit} nonHighlightedTagName="h6" />
<br />
<Snippet attribute="textContent" hit={hit} nonHighlightedTagName="p" tagName="span" />
</>
);
};
const renderSectionTitle = (section: HitProps): React.ReactNode => {
const titles: { [key: string]: any } = {
'0x_tools_test': 'Tools',
'0x_guides_test': 'Guides',
};
return <p>{titles[section.index]}</p>;
};
const getSectionSuggestions = (section: HitProps): string => section.hits;
const inputProps = {
placeholder: 'Search docs',
onChange,
value,
};
return (
<Wrapper isHome={isHome}>
<Autosuggest
suggestions={hits}
multiSection={true}
onSuggestionSelected={onSuggestionSelected}
onSuggestionsFetchRequested={onSuggestionsFetchRequested}
onSuggestionHighlighted={onSuggestionHighlighted}
onSuggestionsClearRequested={onSuggestionsClearRequested}
getSuggestionValue={getSuggestionValue}
renderSuggestion={renderSuggestion}
inputProps={inputProps}
renderSectionTitle={renderSectionTitle}
getSectionSuggestions={getSectionSuggestions}
/>
</Wrapper>
);
};
const Overlay = styled.div`
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: #000;
opacity: 0.5;
pointer-events: none;
`;
const Wrapper = styled.div<Props>`
position: relative;
${({ isHome }) =>
isHome &&
`
width: calc(100% - 60px);
max-width: 900px;
margin: 0 auto;
`};
.react-autosuggest__input {
background: url("data:image/svg+xml,%3Csvg width='24' height='24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23fff' fill-opacity='.01' d='M0 0h24v24H0z'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M5 10.5a5.5 5.5 0 1 1 11 0 5.5 5.5 0 0 1-11 0zM10.5 3a7.5 7.5 0 1 0 4.55 13.463l4.743 4.744 1.414-1.414-4.744-4.744A7.5 7.5 0 0 0 10.5 3z' fill='%235C5C5C'/%3E%3C/svg%3E")
transparent left center no-repeat;
font-size: 22px;
padding: 18px 18px 21px 35px;
width: 100%;
border: 0;
border-bottom: 1px solid #b4bebd;
outline: none;
&--open {
border-bottom-color: ${colors.brandLight};
}
@media (max-width: 900px) {
border: none;
}
${({ isHome }) =>
!isHome &&
`
background-color: #EBEEEC;
border-bottom: 0;
padding: 13px 21px 15px 52px;
background-position: left 21px center;
font-size: 1rem;
&--focused,
&--open {
background-color: white;
}
`};
&:before {
content: '';
width: 30px;
height: 30px;
opacity: 0.15;
position: absolute;
top: 0;
left: 0;
}
}
.react-autosuggest__container {
border: 1px solid orangered;
&--open {
background-color: ${colors.white};
border-color: #dbdfdd;
}
${({ isHome }) =>
isHome &&
`
padding: 13px 30px;
@media (max-width: 900px) {
padding: 13px 18px;
}
`};
}
.react-autosuggest__section-container {
display: flex;
@media (max-width: 900px) {
flex-direction: column;
}
}
.react-autosuggest__section-title {
text-align: center;
min-width: 180px;
p {
width: max-content;
float: left;
color: ${colors.brandDark};
background-color: rgba(0, 56, 49, 0.1);
border-radius: 4px;
font-size: 12px;
text-transform: uppercase;
position: sticky;
top: 0px;
margin: 30px;
padding: 4px 10px 2px;
line-height: 1.4;
}
@media (max-width: 900px) {
min-width: 100%;
p {
margin: 0;
padding: 10px 18px 8px;
border-radius: 0;
width: 100%;
}
}
}
.react-autosuggest__suggestions-container {
position: absolute;
right: 0;
left: 0;
background-color: ${colors.white};
z-index: 10;
flex-grow: 1;
&--open {
border: 1px solid #dbdfdd;
border-top: none;
}
${({ isHome }) =>
!isHome &&
`
top: 50px;
`};
}
.react-autosuggest__suggestions-list {
flex-grow: 1;
width: 100%;
}
.react-autosuggest__suggestion {
display: flex;
flex-direction: column;
border-bottom: 1px solid #eee;
min-height: 110px;
padding: 25px 30px;
margin-right: 30px;
transition: background-color 300ms ease-in-out;
&--highlighted {
background-color: ${colors.backgroundLight};
}
@media (max-width: 900px) {
padding: 25px 18px;
margin-right: 0;
}
h6 {
display: inline;
color: ${colors.brandDark};
font-size: var(--smallHeading);
font-weight: 300;
}
em {
font-size: var(--smallHeading);
font-weight: 400;
}
p {
display: inline;
color: ${colors.textDarkSecondary};
font-size: var(--smallParagraph);
font-weight: 300;
}
span {
font-size: var(--smallParagraph);
font-weight: 400;
}
}
`;