Commit 29e8a6b8 authored by tom's avatar tom

SPA transition for search bar

parent df59efab
import { Popover, PopoverTrigger, PopoverContent, PopoverBody, useDisclosure } from '@chakra-ui/react';
import _debounce from 'lodash/debounce';
import { useRouter } from 'next/router';
import { route } from 'nextjs-routes';
import type { FormEvent, FocusEvent } from 'react';
import React from 'react';
......@@ -21,6 +22,7 @@ const SearchBar = ({ isHomepage }: Props) => {
const menuRef = React.useRef<HTMLDivElement>(null);
const menuWidth = React.useRef<number>(0);
const isMobile = useIsMobile();
const router = useRouter();
const { searchTerm, handleSearchTermChange, query, pathname } = useSearchQuery();
......@@ -33,9 +35,9 @@ const SearchBar = ({ isHomepage }: Props) => {
'Source page type': mixpanel.getPageType(pathname),
'Result URL': url,
});
window.location.assign(url);
router.push({ pathname: '/search-results', query: { q: searchTerm } }, undefined, { shallow: true });
}
}, [ searchTerm, pathname ]);
}, [ searchTerm, pathname, router ]);
const handleFocus = React.useCallback(() => {
onOpen();
......@@ -59,6 +61,15 @@ const SearchBar = ({ isHomepage }: Props) => {
inputRef.current?.querySelector('input')?.focus();
}, [ handleSearchTermChange ]);
const handleItemClick = React.useCallback((event: React.MouseEvent<HTMLAnchorElement>) => {
mixpanel.logEvent(mixpanel.EventTypes.SEARCH_QUERY, {
'Search query': searchTerm,
'Source page type': mixpanel.getPageType(pathname),
'Result URL': event.currentTarget.href,
});
onClose();
}, [ pathname, searchTerm, onClose ]);
const menuPaddingX = isMobile && !isHomepage ? 32 : 0;
const calculateMenuWidth = React.useCallback(() => {
menuWidth.current = (inputRef.current?.getBoundingClientRect().width || 0) - menuPaddingX;
......@@ -104,7 +115,7 @@ const SearchBar = ({ isHomepage }: Props) => {
</PopoverTrigger>
<PopoverContent w={ `${ menuWidth.current }px` } maxH={{ base: '300px', lg: '500px' }} overflowY="scroll" ref={ menuRef }>
<PopoverBody py={ 6 }>
<SearchBarSuggest query={ query } searchTerm={ searchTerm } pathname={ pathname }/>
<SearchBarSuggest query={ query } searchTerm={ searchTerm } onItemClick={ handleItemClick }/>
</PopoverBody>
</PopoverContent>
</Popover>
......
import { Text } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query';
import type { Route } from 'nextjs-routes';
import React from 'react';
import type { SearchResult } from 'types/api/search';
......@@ -17,10 +16,10 @@ interface Props {
pagination: PaginationProps;
};
searchTerm: string;
pathname: Route['pathname'];
onItemClick: (event: React.MouseEvent<HTMLAnchorElement>) => void;
}
const SearchBarSuggest = ({ query, searchTerm, pathname }: Props) => {
const SearchBarSuggest = ({ query, searchTerm, onItemClick }: Props) => {
const isMobile = useIsMobile();
const content = (() => {
......@@ -39,7 +38,7 @@ const SearchBarSuggest = ({ query, searchTerm, pathname }: Props) => {
<>
<Text fontWeight={ 500 } fontSize="sm">Found <Text fontWeight={ 700 } as="span">{ num }</Text> matching { resultText }</Text>
{ query.data.items.map((item, index) =>
<SearchBarSuggestItem key={ index } data={ item } isMobile={ isMobile } searchTerm={ searchTerm } pathname={ pathname }/>) }
<SearchBarSuggestItem key={ index } data={ item } isMobile={ isMobile } searchTerm={ searchTerm } onClick={ onItemClick }/>) }
</>
);
})();
......
import { chakra, Text, Flex, useColorModeValue, Icon, Box } from '@chakra-ui/react';
import type { LinkProps as NextLinkProps } from 'next/link';
import NextLink from 'next/link';
import { route } from 'nextjs-routes';
import type { Route } from 'nextjs-routes';
import React from 'react';
import type { SearchResultItem } from 'types/api/search';
......@@ -8,7 +9,6 @@ import type { SearchResultItem } from 'types/api/search';
import blockIcon from 'icons/block.svg';
import txIcon from 'icons/transactions.svg';
import highlightText from 'lib/highlightText';
import * as mixpanel from 'lib/mixpanel/index';
import AddressIcon from 'ui/shared/address/AddressIcon';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import TokenLogo from 'ui/shared/TokenLogo';
......@@ -17,18 +17,10 @@ interface Props {
data: SearchResultItem;
isMobile: boolean | undefined;
searchTerm: string;
pathname: Route['pathname'];
onClick: (event: React.MouseEvent<HTMLAnchorElement>) => void;
}
const SearchBarSuggestItem = ({ data, isMobile, searchTerm, pathname }: Props) => {
const handleClick = React.useCallback((event: React.MouseEvent<HTMLAnchorElement>) => {
mixpanel.logEvent(mixpanel.EventTypes.SEARCH_QUERY, {
'Search query': searchTerm,
'Source page type': mixpanel.getPageType(pathname),
'Result URL': event.currentTarget.href,
});
}, [ searchTerm, pathname ]);
const SearchBarSuggestItem = ({ data, isMobile, searchTerm, onClick }: Props) => {
const url = (() => {
switch (data.type) {
......@@ -153,32 +145,33 @@ const SearchBarSuggestItem = ({ data, isMobile, searchTerm, pathname }: Props) =
})();
return (
<chakra.a
py={ 3 }
px={ 1 }
display="flex"
flexDir="column"
rowGap={ 2 }
borderColor="divider"
borderBottomWidth="1px"
_last={{
borderBottomWidth: '0',
}}
_hover={{
bgColor: useColorModeValue('blue.50', 'gray.800'),
}}
fontSize="sm"
href={ url }
_first={{
mt: 2,
}}
onClick={ handleClick }
>
<Flex display="flex" alignItems="center">
{ firstRow }
</Flex>
{ secondRow }
</chakra.a>
<NextLink href={ url as NextLinkProps['href'] } passHref legacyBehavior>
<chakra.a
py={ 3 }
px={ 1 }
display="flex"
flexDir="column"
rowGap={ 2 }
borderColor="divider"
borderBottomWidth="1px"
_last={{
borderBottomWidth: '0',
}}
_hover={{
bgColor: useColorModeValue('blue.50', 'gray.800'),
}}
fontSize="sm"
_first={{
mt: 2,
}}
onClick={ onClick }
>
<Flex display="flex" alignItems="center">
{ firstRow }
</Flex>
{ secondRow }
</chakra.a>
</NextLink>
);
};
......
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