Commit 0c1fa3f7 authored by tom's avatar tom

highlight search term

parent ce6b0349
export default function escapeRegExp(string: string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
import escapeRegExp from 'lib/escapeRegExp';
export default function highlightText(text: string, query: string) {
const regex = new RegExp('(' + escapeRegExp(query) + ')', 'gi');
return text.replace(regex, '<mark>$1</mark>');
}
...@@ -9,6 +9,10 @@ const global = (props: StyleFunctionProps) => ({ ...@@ -9,6 +9,10 @@ const global = (props: StyleFunctionProps) => ({
...getDefaultTransitionProps(), ...getDefaultTransitionProps(),
'-webkit-tap-highlight-color': 'transparent', '-webkit-tap-highlight-color': 'transparent',
}, },
mark: {
bgColor: 'yellow.200',
color: 'inherit',
},
'svg *::selection': { 'svg *::selection': {
color: 'none', color: 'none',
background: 'none', background: 'none',
......
...@@ -2,7 +2,6 @@ import { Box, chakra, Table, Tbody, Tr, Th, Skeleton, Show, Hide } from '@chakra ...@@ -2,7 +2,6 @@ import { Box, chakra, Table, Tbody, Tr, Th, Skeleton, Show, Hide } from '@chakra
import type { FormEvent } from 'react'; import type { FormEvent } from 'react';
import React from 'react'; import React from 'react';
import useIsMobile from 'lib/hooks/useIsMobile';
import link from 'lib/link/link'; import link from 'lib/link/link';
import SearchResultListItem from 'ui/searchResults/SearchResultListItem'; import SearchResultListItem from 'ui/searchResults/SearchResultListItem';
import SearchResultTableItem from 'ui/searchResults/SearchResultTableItem'; import SearchResultTableItem from 'ui/searchResults/SearchResultTableItem';
...@@ -21,7 +20,6 @@ import useSearchQuery from 'ui/snippets/searchBar/useSearchQuery'; ...@@ -21,7 +20,6 @@ import useSearchQuery from 'ui/snippets/searchBar/useSearchQuery';
const SearchResultsPageContent = () => { const SearchResultsPageContent = () => {
const { query, searchTerm, handleSearchTermChange } = useSearchQuery(true); const { query, searchTerm, handleSearchTermChange } = useSearchQuery(true);
const { data, isError, isLoading, pagination, isPaginationVisible } = query; const { data, isError, isLoading, pagination, isPaginationVisible } = query;
const isMobile = useIsMobile();
const handleSubmit = React.useCallback((event: FormEvent<HTMLFormElement>) => { const handleSubmit = React.useCallback((event: FormEvent<HTMLFormElement>) => {
event.preventDefault(); event.preventDefault();
...@@ -40,10 +38,10 @@ const SearchResultsPageContent = () => { ...@@ -40,10 +38,10 @@ const SearchResultsPageContent = () => {
return ( return (
<Box> <Box>
<Skeleton h={ 6 } w="280px" borderRadius="full" mb={ 6 }/> <Skeleton h={ 6 } w="280px" borderRadius="full" mb={ 6 }/>
<Show below="lg" ssr={ false }> <Show below="lg">
<SkeletonList/> <SkeletonList/>
</Show> </Show>
<Hide below="lg" ssr={ false }> <Hide below="lg">
<SkeletonTable columns={ [ '33%', '34%', '33%' ] }/> <SkeletonTable columns={ [ '33%', '34%', '33%' ] }/>
</Hide> </Hide>
</Box> </Box>
...@@ -65,22 +63,14 @@ const SearchResultsPageContent = () => { ...@@ -65,22 +63,14 @@ const SearchResultsPageContent = () => {
return text; return text;
} }
if (isMobile) {
return ( return (
<> <>
{ text } <Box display={{ base: 'block', lg: 'none' }}>{ text }</Box>
<ActionBar> <ActionBar mt={{ base: 0, lg: -6 }}>
<Pagination { ...pagination } ml="auto"/> <Box display={{ base: 'none', lg: 'block' }}>{ text }</Box>
</ActionBar>
</>
);
}
return (
<ActionBar mt={ -6 }>
{ text }
<Pagination { ...pagination }/> <Pagination { ...pagination }/>
</ActionBar> </ActionBar>
</>
); );
})(); })();
...@@ -90,7 +80,7 @@ const SearchResultsPageContent = () => { ...@@ -90,7 +80,7 @@ const SearchResultsPageContent = () => {
{ data.items.length > 0 && ( { data.items.length > 0 && (
<> <>
<Show below="lg" ssr={ false }> <Show below="lg" ssr={ false }>
{ data.items.map((item, index) => <SearchResultListItem key={ index } data={ item }/>) } { data.items.map((item, index) => <SearchResultListItem key={ index } data={ item } searchTerm={ searchTerm }/>) }
</Show> </Show>
<Hide below="lg" ssr={ false }> <Hide below="lg" ssr={ false }>
<Table variant="simple" size="md" fontWeight={ 500 }> <Table variant="simple" size="md" fontWeight={ 500 }>
...@@ -102,7 +92,7 @@ const SearchResultsPageContent = () => { ...@@ -102,7 +92,7 @@ const SearchResultsPageContent = () => {
</Tr> </Tr>
</Thead> </Thead>
<Tbody> <Tbody>
{ data.items.map((item, index) => <SearchResultTableItem key={ index } data={ item }/>) } { data.items.map((item, index) => <SearchResultTableItem key={ index } data={ item } searchTerm={ searchTerm }/>) }
</Tbody> </Tbody>
</Table> </Table>
</Hide> </Hide>
......
import { Text, Link, Flex, Icon } from '@chakra-ui/react'; import { Text, Link, Flex, Icon, Box, chakra } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { SearchResultItem } from 'types/api/search'; import type { SearchResultItem } from 'types/api/search';
import blockIcon from 'icons/block.svg'; import blockIcon from 'icons/block.svg';
import txIcon from 'icons/transactions.svg'; import txIcon from 'icons/transactions.svg';
import highlightText from 'lib/highlightText';
import link from 'lib/link/link'; import link from 'lib/link/link';
import Address from 'ui/shared/address/Address'; import Address from 'ui/shared/address/Address';
import AddressIcon from 'ui/shared/address/AddressIcon'; import AddressIcon from 'ui/shared/address/AddressIcon';
...@@ -15,18 +16,21 @@ import TokenLogo from 'ui/shared/TokenLogo'; ...@@ -15,18 +16,21 @@ import TokenLogo from 'ui/shared/TokenLogo';
interface Props { interface Props {
data: SearchResultItem; data: SearchResultItem;
searchTerm: string;
} }
const SearchResultListItem = ({ data }: Props) => { const SearchResultListItem = ({ data, searchTerm }: Props) => {
const firstRow = (() => { const firstRow = (() => {
switch (data.type) { switch (data.type) {
case 'token': { case 'token': {
const name = data.name + (data.symbol ? ` (${ data.symbol })` : '');
return ( return (
<Flex alignItems="center"> <Flex alignItems="center">
<TokenLogo boxSize={ 6 } hash={ data.address } name={ data.name }/> <TokenLogo boxSize={ 6 } hash={ data.address } name={ data.name }/>
<Link ml={ 2 } href={ link('token_index', { hash: data.address }) } fontWeight={ 700 }> <Link ml={ 2 } href={ link('token_index', { hash: data.address }) } fontWeight={ 700 }>
{ data.name }{ data.symbol ? ` (${ data.symbol })` : '' } <span dangerouslySetInnerHTML={{ __html: highlightText(name, searchTerm) }}/>
</Link> </Link>
</Flex> </Flex>
); );
...@@ -34,20 +38,24 @@ const SearchResultListItem = ({ data }: Props) => { ...@@ -34,20 +38,24 @@ const SearchResultListItem = ({ data }: Props) => {
case 'contract': case 'contract':
case 'address': { case 'address': {
const shouldHighlightHash = data.address.toLowerCase() === searchTerm.toLowerCase();
return ( return (
<Address> <Address>
<AddressIcon hash={ data.address }/> <AddressIcon hash={ data.address } mr={ 2 }/>
<AddressLink hash={ data.address } ml={ 2 } fontWeight={ 700 }/> <Box as={ shouldHighlightHash ? 'mark' : 'span' } display="block" whiteSpace="nowrap" overflow="hidden">
<AddressLink hash={ data.address } fontWeight={ 700 } display="block" w="100%"/>
</Box>
</Address> </Address>
); );
} }
case 'block': { case 'block': {
const shouldHighlightHash = data.block_hash.toLowerCase() === searchTerm.toLowerCase();
return ( return (
<Flex alignItems="center"> <Flex alignItems="center">
<Icon as={ blockIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/> <Icon as={ blockIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/>
<Link fontWeight={ 700 } href={ link('block', { id: String(data.block_number) }) }> <Link fontWeight={ 700 } href={ link('block', { id: String(data.block_number) }) }>
{ data.block_number } <Box as={ shouldHighlightHash ? 'span' : 'mark' }>{ data.block_number }</Box>
</Link> </Link>
</Flex> </Flex>
); );
...@@ -57,9 +65,9 @@ const SearchResultListItem = ({ data }: Props) => { ...@@ -57,9 +65,9 @@ const SearchResultListItem = ({ data }: Props) => {
return ( return (
<Flex alignItems="center" overflow="hidden"> <Flex alignItems="center" overflow="hidden">
<Icon as={ txIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/> <Icon as={ txIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/>
<Address> <chakra.mark display="block" overflow="hidden">
<AddressLink hash={ data.tx_hash } type="transaction" fontWeight={ 700 }/> <AddressLink hash={ data.tx_hash } type="transaction" fontWeight={ 700 } display="block"/>
</Address> </chakra.mark>
</Flex> </Flex>
); );
} }
...@@ -74,13 +82,17 @@ const SearchResultListItem = ({ data }: Props) => { ...@@ -74,13 +82,17 @@ const SearchResultListItem = ({ data }: Props) => {
); );
} }
case 'block': { case 'block': {
const shouldHighlightHash = data.block_hash.toLowerCase() === searchTerm.toLowerCase();
return ( return (
<Box as={ shouldHighlightHash ? 'mark' : 'span' } display="block" w="100%" whiteSpace="nowrap" overflow="hidden">
<HashStringShortenDynamic hash={ data.block_hash }/> <HashStringShortenDynamic hash={ data.block_hash }/>
</Box>
); );
} }
case 'contract': case 'contract':
case 'address': { case 'address': {
return data.name ? <Text>{ data.name }</Text> : null; const shouldHighlightHash = data.address.toLowerCase() === searchTerm.toLowerCase();
return data.name ? <span dangerouslySetInnerHTML={{ __html: shouldHighlightHash ? data.name : highlightText(data.name, searchTerm) }}/> : null;
} }
default: default:
......
...@@ -5,6 +5,7 @@ import type { SearchResultItem } from 'types/api/search'; ...@@ -5,6 +5,7 @@ import type { SearchResultItem } from 'types/api/search';
import blockIcon from 'icons/block.svg'; import blockIcon from 'icons/block.svg';
import txIcon from 'icons/transactions.svg'; import txIcon from 'icons/transactions.svg';
import highlightText from 'lib/highlightText';
import link from 'lib/link/link'; import link from 'lib/link/link';
import Address from 'ui/shared/address/Address'; import Address from 'ui/shared/address/Address';
import AddressIcon from 'ui/shared/address/AddressIcon'; import AddressIcon from 'ui/shared/address/AddressIcon';
...@@ -14,22 +15,22 @@ import TokenLogo from 'ui/shared/TokenLogo'; ...@@ -14,22 +15,22 @@ import TokenLogo from 'ui/shared/TokenLogo';
interface Props { interface Props {
data: SearchResultItem; data: SearchResultItem;
searchTerm: string;
} }
const SearchResultTableItem = ({ data }: Props) => { const SearchResultTableItem = ({ data, searchTerm }: Props) => {
const content = (() => { const content = (() => {
switch (data.type) { switch (data.type) {
case 'token': { case 'token': {
const name = data.name + (data.symbol ? ` (${ data.symbol })` : '');
return ( return (
<> <>
<Td fontSize="sm"> <Td fontSize="sm">
<Flex alignItems="center"> <Flex alignItems="center">
<TokenLogo boxSize={ 6 } hash={ data.address } name={ data.name }/> <TokenLogo boxSize={ 6 } hash={ data.address } name={ data.name }/>
<Link ml={ 2 } href={ link('token_index', { hash: data.address }) } fontWeight={ 700 }> <Link ml={ 2 } href={ link('token_index', { hash: data.address }) } fontWeight={ 700 }>
<span> <span dangerouslySetInnerHTML={{ __html: highlightText(name, searchTerm) }}/>
{ data.name }{ data.symbol ? ` (${ data.symbol })` : '' }
</span>
</Link> </Link>
</Flex> </Flex>
</Td> </Td>
...@@ -45,16 +46,21 @@ const SearchResultTableItem = ({ data }: Props) => { ...@@ -45,16 +46,21 @@ const SearchResultTableItem = ({ data }: Props) => {
case 'contract': case 'contract':
case 'address': { case 'address': {
if (data.name) { if (data.name) {
const shouldHighlightHash = data.address.toLowerCase() === searchTerm.toLowerCase();
return ( return (
<> <>
<Td fontSize="sm"> <Td fontSize="sm">
<Address> <Flex alignItems="center" overflow="hidden">
<AddressIcon hash={ data.address }/> <AddressIcon hash={ data.address } mr={ 2 }/>
<AddressLink fontWeight={ 700 } ml={ 2 } hash={ data.address }/> <Link href={ link('address_index', { id: data.address }) } fontWeight={ 700 } overflow="hidden" whiteSpace="nowrap">
</Address> <Box as={ shouldHighlightHash ? 'mark' : 'span' } display="block">
<HashStringShortenDynamic hash={ data.address }/>
</Box>
</Link>
</Flex>
</Td> </Td>
<Td fontSize="sm" verticalAlign="middle"> <Td fontSize="sm" verticalAlign="middle">
{ data.name } <span dangerouslySetInnerHTML={{ __html: shouldHighlightHash ? data.name : highlightText(data.name, searchTerm) }}/>
</Td> </Td>
</> </>
); );
...@@ -63,26 +69,30 @@ const SearchResultTableItem = ({ data }: Props) => { ...@@ -63,26 +69,30 @@ const SearchResultTableItem = ({ data }: Props) => {
return ( return (
<Td colSpan={ 2 } fontSize="sm"> <Td colSpan={ 2 } fontSize="sm">
<Address> <Address>
<AddressIcon hash={ data.address }/> <AddressIcon hash={ data.address } mr={ 2 }/>
<AddressLink hash={ data.address } ml={ 2 } type="address" fontWeight={ 700 }/> <mark>
<AddressLink hash={ data.address } type="address" fontWeight={ 700 }/>
</mark>
</Address> </Address>
</Td> </Td>
); );
} }
case 'block': { case 'block': {
const shouldHighlightHash = data.block_hash.toLowerCase() === searchTerm.toLowerCase();
return ( return (
<> <>
<Td fontSize="sm"> <Td fontSize="sm">
<Flex alignItems="center"> <Flex alignItems="center">
<Icon as={ blockIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/> <Icon as={ blockIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/>
<Link fontWeight={ 700 } href={ link('block', { id: String(data.block_number) }) }> <Link fontWeight={ 700 } href={ link('block', { id: String(data.block_number) }) }>
{ data.block_number } <Box as={ shouldHighlightHash ? 'span' : 'mark' }>{ data.block_number }</Box>
</Link> </Link>
</Flex> </Flex>
</Td> </Td>
<Td fontSize="sm" verticalAlign="middle"> <Td fontSize="sm" verticalAlign="middle">
<Box overflow="hidden" whiteSpace="nowrap"> <Box overflow="hidden" whiteSpace="nowrap" as={ shouldHighlightHash ? 'mark' : 'span' } display="block">
<HashStringShortenDynamic hash={ data.block_hash }/> <HashStringShortenDynamic hash={ data.block_hash }/>
</Box> </Box>
</Td> </Td>
...@@ -95,9 +105,9 @@ const SearchResultTableItem = ({ data }: Props) => { ...@@ -95,9 +105,9 @@ const SearchResultTableItem = ({ data }: Props) => {
<Td colSpan={ 2 } fontSize="sm"> <Td colSpan={ 2 } fontSize="sm">
<Flex alignItems="center"> <Flex alignItems="center">
<Icon as={ txIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/> <Icon as={ txIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/>
<Address> <mark>
<AddressLink hash={ data.tx_hash } type="transaction" fontWeight={ 700 }/> <AddressLink hash={ data.tx_hash } type="transaction" fontWeight={ 700 }/>
</Address> </mark>
</Flex> </Flex>
</Td> </Td>
); );
......
...@@ -77,7 +77,7 @@ const SearchBar = ({ isHomepage, withShadow }: Props) => { ...@@ -77,7 +77,7 @@ const SearchBar = ({ isHomepage, withShadow }: Props) => {
</PopoverTrigger> </PopoverTrigger>
<PopoverContent w={ `${ menuWidth.current }px` } maxH={{ base: '300px', lg: '500px' }} overflowY="scroll" ref={ menuRef }> <PopoverContent w={ `${ menuWidth.current }px` } maxH={{ base: '300px', lg: '500px' }} overflowY="scroll" ref={ menuRef }>
<PopoverBody py={ 6 }> <PopoverBody py={ 6 }>
<SearchBarSuggest query={ query }/> <SearchBarSuggest query={ query } searchTerm={ searchTerm }/>
</PopoverBody> </PopoverBody>
</PopoverContent> </PopoverContent>
</Popover> </Popover>
......
...@@ -11,9 +11,10 @@ import SearchBarSuggestItem from './SearchBarSuggestItem'; ...@@ -11,9 +11,10 @@ import SearchBarSuggestItem from './SearchBarSuggestItem';
interface Props { interface Props {
query: UseQueryResult<SearchResult>; query: UseQueryResult<SearchResult>;
searchTerm: string;
} }
const SearchBarSuggest = ({ query }: Props) => { const SearchBarSuggest = ({ query, searchTerm }: Props) => {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const content = (() => { const content = (() => {
...@@ -31,7 +32,7 @@ const SearchBarSuggest = ({ query }: Props) => { ...@@ -31,7 +32,7 @@ const SearchBarSuggest = ({ query }: Props) => {
return ( return (
<> <>
<Box fontWeight={ 500 } fontSize="sm">Found <Text fontWeight={ 700 } as="span">{ num }</Text> matching results</Box> <Box fontWeight={ 500 } fontSize="sm">Found <Text fontWeight={ 700 } as="span">{ num }</Text> matching results</Box>
{ query.data.items.map((item, index) => <SearchBarSuggestItem key={ index } data={ item } isMobile={ isMobile }/>) } { query.data.items.map((item, index) => <SearchBarSuggestItem key={ index } data={ item } isMobile={ isMobile } searchTerm={ searchTerm }/>) }
</> </>
); );
})(); })();
......
import { chakra, Text, Flex, useColorModeValue, Icon } from '@chakra-ui/react'; import { chakra, Text, Flex, useColorModeValue, Icon, Box } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { SearchResultItem } from 'types/api/search'; import type { SearchResultItem } from 'types/api/search';
import blockIcon from 'icons/block.svg'; import blockIcon from 'icons/block.svg';
import txIcon from 'icons/transactions.svg'; import txIcon from 'icons/transactions.svg';
import highlightText from 'lib/highlightText';
import link from 'lib/link/link'; import link from 'lib/link/link';
import AddressIcon from 'ui/shared/address/AddressIcon'; import AddressIcon from 'ui/shared/address/AddressIcon';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic'; import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
...@@ -13,9 +14,10 @@ import TokenLogo from 'ui/shared/TokenLogo'; ...@@ -13,9 +14,10 @@ import TokenLogo from 'ui/shared/TokenLogo';
interface Props { interface Props {
data: SearchResultItem; data: SearchResultItem;
isMobile: boolean | undefined; isMobile: boolean | undefined;
searchTerm: string;
} }
const SearchBarSuggestItem = ({ data, isMobile }: Props) => { const SearchBarSuggestItem = ({ data, isMobile, searchTerm }: Props) => {
const url = (() => { const url = (() => {
switch (data.type) { switch (data.type) {
...@@ -38,12 +40,13 @@ const SearchBarSuggestItem = ({ data, isMobile }: Props) => { ...@@ -38,12 +40,13 @@ const SearchBarSuggestItem = ({ data, isMobile }: Props) => {
const firstRow = (() => { const firstRow = (() => {
switch (data.type) { switch (data.type) {
case 'token': { case 'token': {
const name = data.name + (data.symbol ? ` (${ data.symbol })` : '');
return ( return (
<> <>
<TokenLogo boxSize={ 6 } hash={ data.address } name={ data.name } flexShrink={ 0 }/> <TokenLogo boxSize={ 6 } hash={ data.address } name={ data.name } flexShrink={ 0 }/>
<Text fontWeight={ 700 } ml={ 2 } w="200px" overflow="hidden" whiteSpace="nowrap" textOverflow="ellipsis" flexShrink={ 0 }> <Text fontWeight={ 700 } ml={ 2 } w="200px" overflow="hidden" whiteSpace="nowrap" textOverflow="ellipsis" flexShrink={ 0 }>
<span>{ data.name }</span> <span dangerouslySetInnerHTML={{ __html: highlightText(name, searchTerm) }}/>
{ data.symbol && <span> ({ data.symbol })</span> }
</Text> </Text>
{ !isMobile && ( { !isMobile && (
<Text overflow="hidden" whiteSpace="nowrap" ml={ 2 } variant="secondary"> <Text overflow="hidden" whiteSpace="nowrap" ml={ 2 } variant="secondary">
...@@ -55,27 +58,29 @@ const SearchBarSuggestItem = ({ data, isMobile }: Props) => { ...@@ -55,27 +58,29 @@ const SearchBarSuggestItem = ({ data, isMobile }: Props) => {
} }
case 'contract': case 'contract':
case 'address': { case 'address': {
const shouldHighlightHash = data.address.toLowerCase() === searchTerm.toLowerCase();
return ( return (
<> <>
<AddressIcon hash={ data.address } mr={ 2 }/> <AddressIcon hash={ data.address } mr={ 2 }/>
<chakra.span overflow="hidden" whiteSpace="nowrap" fontWeight={ 700 }> <Box as={ shouldHighlightHash ? 'mark' : 'span' } display="block" overflow="hidden" whiteSpace="nowrap" fontWeight={ 700 }>
<HashStringShortenDynamic hash={ data.address } isTooltipDisabled/> <HashStringShortenDynamic hash={ data.address } isTooltipDisabled/>
</chakra.span> </Box>
{ !isMobile && ( { !isMobile && data.name && (
<Text variant="secondary" ml={ 2 }> <Text variant="secondary" ml={ 2 }>
{ data.name } <span dangerouslySetInnerHTML={{ __html: shouldHighlightHash ? data.name : highlightText(data.name, searchTerm) }}/>
</Text> </Text>
) } ) }
</> </>
); );
} }
case 'block': { case 'block': {
const shouldHighlightHash = data.block_hash.toLowerCase() === searchTerm.toLowerCase();
return ( return (
<> <>
<Icon as={ blockIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/> <Icon as={ blockIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/>
<chakra.span fontWeight={ 700 }>{ data.block_number }</chakra.span> <Box fontWeight={ 700 } as={ shouldHighlightHash ? 'span' : 'mark' }>{ data.block_number }</Box>
{ !isMobile && ( { !isMobile && (
<Text variant="secondary" overflow="hidden" whiteSpace="nowrap" ml={ 2 }> <Text variant="secondary" overflow="hidden" whiteSpace="nowrap" ml={ 2 } as={ shouldHighlightHash ? 'mark' : 'span' } display="block">
<HashStringShortenDynamic hash={ data.block_hash } isTooltipDisabled/> <HashStringShortenDynamic hash={ data.block_hash } isTooltipDisabled/>
</Text> </Text>
) } ) }
...@@ -86,9 +91,9 @@ const SearchBarSuggestItem = ({ data, isMobile }: Props) => { ...@@ -86,9 +91,9 @@ const SearchBarSuggestItem = ({ data, isMobile }: Props) => {
return ( return (
< > < >
<Icon as={ txIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/> <Icon as={ txIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/>
<chakra.span overflow="hidden" whiteSpace="nowrap" fontWeight={ 700 }> <chakra.mark overflow="hidden" whiteSpace="nowrap" fontWeight={ 700 }>
<HashStringShortenDynamic hash={ data.tx_hash } isTooltipDisabled/> <HashStringShortenDynamic hash={ data.tx_hash } isTooltipDisabled/>
</chakra.span> </chakra.mark>
</> </>
); );
} }
...@@ -109,17 +114,23 @@ const SearchBarSuggestItem = ({ data, isMobile }: Props) => { ...@@ -109,17 +114,23 @@ const SearchBarSuggestItem = ({ data, isMobile }: Props) => {
); );
} }
case 'block': { case 'block': {
const shouldHighlightHash = data.block_hash.toLowerCase() === searchTerm.toLowerCase();
return ( return (
<Text variant="secondary" whiteSpace="nowrap" overflow="hidden"> <Text variant="secondary" whiteSpace="nowrap" overflow="hidden" as={ shouldHighlightHash ? 'mark' : 'span' } display="block">
<HashStringShortenDynamic hash={ data.block_hash } isTooltipDisabled/> <HashStringShortenDynamic hash={ data.block_hash } isTooltipDisabled/>
</Text> </Text>
); );
} }
case 'contract': case 'contract':
case 'address': { case 'address': {
if (!data.name) {
return null;
}
const shouldHighlightHash = data.address.toLowerCase() === searchTerm.toLowerCase();
return ( return (
<Text variant="secondary" whiteSpace="nowrap" overflow="hidden"> <Text variant="secondary" whiteSpace="nowrap" overflow="hidden">
{ data.name } <span dangerouslySetInnerHTML={{ __html: shouldHighlightHash ? data.name : highlightText(data.name, searchTerm) }}/>
</Text> </Text>
); );
} }
......
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