Commit 7019554e authored by tom goriunov's avatar tom goriunov Committed by GitHub

Dim out page to focus on a search (#1711)

* Dim out page to focus on a search

Fixes #1682

* add backdrop to search results page

* refactoring
parent 4dc76f69
......@@ -46,6 +46,11 @@ NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
NEXT_PUBLIC_AD_BANNER_PROVIDER=hype
NEXT_PUBLIC_SAFE_TX_SERVICE_URL=https://safe-transaction-mainnet.safe.global
NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
NEXT_PUBLIC_MARKETPLACE_ENABLED=true
NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-categories/default.json
NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-categories/default.json
NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
#meta
NEXT_PUBLIC_OG_IMAGE_URL=https://github.com/blockscout/frontend-configs/blob/main/configs/og-images/eth.jpg?raw=true
......@@ -5,6 +5,7 @@ import React from 'react';
import useIsMobile from 'lib/hooks/useIsMobile';
import { getRecentSearchKeywords } from 'lib/recentSearchKeywords';
import SearchBarBackdrop from 'ui/snippets/searchBar/SearchBarBackdrop';
import SearchBarInput from 'ui/snippets/searchBar/SearchBarInput';
import SearchBarRecentKeywords from 'ui/snippets/searchBar/SearchBarRecentKeywords';
......@@ -66,33 +67,39 @@ const SearchResultsInput = ({ searchTerm, handleSubmit, handleSearchTermChange }
};
}, [ calculateMenuWidth ]);
const isSuggestOpen = isOpen && recentSearchKeywords.length > 0 && searchTerm.trim().length === 0;
return (
<Popover
isOpen={ isOpen && recentSearchKeywords.length > 0 && searchTerm.trim().length === 0 }
autoFocus={ false }
onClose={ onClose }
placement="bottom-start"
offset={ isMobile ? [ 16, -12 ] : undefined }
isLazy
>
<PopoverTrigger>
<SearchBarInput
ref={ inputRef }
onChange={ handleSearchTermChange }
onSubmit={ handleSubmit }
onFocus={ handleFocus }
onBlur={ handleBlur }
onHide={ handelHide }
onClear={ handleClear }
value={ searchTerm }
/>
</PopoverTrigger>
<PopoverContent w={ `${ menuWidth.current }px` } maxH={{ base: '300px', lg: '500px' }} overflowY="scroll" ref={ menuRef }>
<PopoverBody py={ 6 }>
<SearchBarRecentKeywords onClick={ handleSearchTermChange } onClear={ onClose }/>
</PopoverBody>
</PopoverContent>
</Popover>
<>
<Popover
isOpen={ isSuggestOpen }
autoFocus={ false }
onClose={ onClose }
placement="bottom-start"
offset={ isMobile ? [ 16, -12 ] : undefined }
isLazy
>
<PopoverTrigger>
<SearchBarInput
ref={ inputRef }
onChange={ handleSearchTermChange }
onSubmit={ handleSubmit }
onFocus={ handleFocus }
onBlur={ handleBlur }
onHide={ handelHide }
onClear={ handleClear }
value={ searchTerm }
isSuggestOpen={ isSuggestOpen }
/>
</PopoverTrigger>
<PopoverContent w={ `${ menuWidth.current }px` } maxH={{ base: '300px', lg: '500px' }} overflowY="scroll" ref={ menuRef }>
<PopoverBody py={ 6 }>
<SearchBarRecentKeywords onClick={ handleSearchTermChange } onClear={ onClose }/>
</PopoverBody>
</PopoverContent>
</Popover>
<SearchBarBackdrop isOpen={ isSuggestOpen }/>
</>
);
};
......
import { Box, Portal, Popover, PopoverTrigger, PopoverContent, PopoverBody, useDisclosure, PopoverFooter, useOutsideClick } from '@chakra-ui/react';
import {
Box,
Portal,
Popover,
PopoverTrigger,
PopoverContent,
PopoverBody,
PopoverFooter,
useDisclosure,
useOutsideClick,
} from '@chakra-ui/react';
import _debounce from 'lodash/debounce';
import { useRouter } from 'next/router';
import type { FormEvent } from 'react';
......@@ -12,6 +22,7 @@ import * as mixpanel from 'lib/mixpanel/index';
import { getRecentSearchKeywords, saveToRecentKeywords } from 'lib/recentSearchKeywords';
import LinkInternal from 'ui/shared/LinkInternal';
import SearchBarBackdrop from './SearchBarBackdrop';
import SearchBarInput from './SearchBarInput';
import SearchBarRecentKeywords from './SearchBarRecentKeywords';
import SearchBarSuggest from './SearchBarSuggest/SearchBarSuggest';
......@@ -106,69 +117,73 @@ const SearchBar = ({ isHomepage }: Props) => {
}, [ calculateMenuWidth ]);
return (
<Popover
isOpen={ isOpen && (searchTerm.trim().length > 0 || recentSearchKeywords.length > 0) }
autoFocus={ false }
onClose={ onClose }
placement="bottom-start"
offset={ isMobile && !isHomepage ? [ 16, -4 ] : undefined }
isLazy
>
<PopoverTrigger>
<SearchBarInput
ref={ inputRef }
onChange={ handleSearchTermChange }
onSubmit={ handleSubmit }
onFocus={ handleFocus }
onHide={ handelHide }
onClear={ handleClear }
isHomepage={ isHomepage }
value={ searchTerm }
/>
</PopoverTrigger>
<Portal>
<PopoverContent
w={ `${ menuWidth.current }px` }
ref={ menuRef }
>
<PopoverBody
p={ 0 }
color="chakra-body-text"
<>
<Popover
isOpen={ isOpen && (searchTerm.trim().length > 0 || recentSearchKeywords.length > 0) }
autoFocus={ false }
onClose={ onClose }
placement="bottom-start"
offset={ isMobile && !isHomepage ? [ 16, -4 ] : undefined }
isLazy
>
<PopoverTrigger>
<SearchBarInput
ref={ inputRef }
onChange={ handleSearchTermChange }
onSubmit={ handleSubmit }
onFocus={ handleFocus }
onHide={ handelHide }
onClear={ handleClear }
isHomepage={ isHomepage }
value={ searchTerm }
isSuggestOpen={ isOpen }
/>
</PopoverTrigger>
<Portal>
<PopoverContent
w={ `${ menuWidth.current }px` }
ref={ menuRef }
>
<Box
maxH="50vh"
overflowY="auto"
id={ SCROLL_CONTAINER_ID }
ref={ scrollRef }
as={ Element }
px={ 4 }
<PopoverBody
p={ 0 }
color="chakra-body-text"
>
{ searchTerm.trim().length === 0 && recentSearchKeywords.length > 0 && (
<SearchBarRecentKeywords onClick={ handleSearchTermChange } onClear={ onClose }/>
) }
{ searchTerm.trim().length > 0 && (
<SearchBarSuggest
query={ query }
searchTerm={ debouncedSearchTerm }
onItemClick={ handleItemClick }
containerId={ SCROLL_CONTAINER_ID }
/>
) }
</Box>
</PopoverBody>
{ searchTerm.trim().length > 0 && query.data && query.data.length >= 50 && (
<PopoverFooter>
<LinkInternal
href={ route({ pathname: '/search-results', query: { q: searchTerm } }) }
fontSize="sm"
<Box
maxH="50vh"
overflowY="auto"
id={ SCROLL_CONTAINER_ID }
ref={ scrollRef }
as={ Element }
px={ 4 }
>
View all results
</LinkInternal>
</PopoverFooter>
) }
</PopoverContent>
</Portal>
</Popover>
{ searchTerm.trim().length === 0 && recentSearchKeywords.length > 0 && (
<SearchBarRecentKeywords onClick={ handleSearchTermChange } onClear={ onClose }/>
) }
{ searchTerm.trim().length > 0 && (
<SearchBarSuggest
query={ query }
searchTerm={ debouncedSearchTerm }
onItemClick={ handleItemClick }
containerId={ SCROLL_CONTAINER_ID }
/>
) }
</Box>
</PopoverBody>
{ searchTerm.trim().length > 0 && query.data && query.data.length >= 50 && (
<PopoverFooter>
<LinkInternal
href={ route({ pathname: '/search-results', query: { q: searchTerm } }) }
fontSize="sm"
>
View all results
</LinkInternal>
</PopoverFooter>
) }
</PopoverContent>
</Portal>
</Popover>
<SearchBarBackdrop isOpen={ isOpen }/>
</>
);
};
......
import { Box, useColorModeValue } from '@chakra-ui/react';
import React from 'react';
interface Props {
isOpen: boolean;
}
const SearchBarBackdrop = ({ isOpen }: Props) => {
const backdropBgColor = useColorModeValue('blackAlpha.400', 'blackAlpha.600');
return (
<Box
position="fixed"
top={ 0 }
left={ 0 }
w="100vw"
h="100vh"
bgColor={ backdropBgColor }
zIndex="overlay"
display={{ base: 'none', lg: isOpen ? 'block' : 'none' }}
/>
);
};
export default React.memo(SearchBarBackdrop);
......@@ -16,10 +16,14 @@ interface Props {
onHide?: () => void;
onClear: () => void;
isHomepage?: boolean;
isSuggestOpen?: boolean;
value: string;
}
const SearchBarInput = ({ onChange, onSubmit, isHomepage, onFocus, onBlur, onHide, onClear, value }: Props, ref: React.ForwardedRef<HTMLFormElement>) => {
const SearchBarInput = (
{ onChange, onSubmit, isHomepage, isSuggestOpen, onFocus, onBlur, onHide, onClear, value }: Props,
ref: React.ForwardedRef<HTMLFormElement>,
) => {
const innerRef = React.useRef<HTMLFormElement>(null);
React.useImperativeHandle(ref, () => innerRef.current as HTMLFormElement, []);
const [ isSticky, setIsSticky ] = React.useState(false);
......@@ -71,10 +75,10 @@ const SearchBarInput = ({ onChange, onSubmit, isHomepage, onFocus, onBlur, onHid
w="100%"
backgroundColor={ bgColor }
borderRadius={{ base: isHomepage ? 'base' : 'none', lg: 'base' }}
position={{ base: isHomepage ? 'static' : 'absolute', lg: 'static' }}
position={{ base: isHomepage ? 'static' : 'absolute', lg: 'relative' }}
top={{ base: isHomepage ? 0 : 55, lg: 0 }}
left="0"
zIndex={{ base: isHomepage ? 'auto' : '-1', lg: 'auto' }}
zIndex={{ base: isHomepage ? 'auto' : '-1', lg: isSuggestOpen ? 'popover' : 'auto' }}
paddingX={{ base: isHomepage ? 0 : 4, lg: 0 }}
paddingTop={{ base: isHomepage ? 0 : 1, lg: 0 }}
paddingBottom={{ base: isHomepage ? 0 : 2, lg: 0 }}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment