Commit 7d985e2a authored by tom goriunov's avatar tom goriunov Committed by GitHub

Merge pull request #603 from blockscout/mobile-tooltip

mobile tooltip fixes
parents e193c49b 50b78567
import { Accordion, AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, Box, Flex, Icon, Link, Tooltip } from '@chakra-ui/react'; import { Accordion, AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, Box, Flex, Link } from '@chakra-ui/react';
import _range from 'lodash/range'; import _range from 'lodash/range';
import React from 'react'; import React from 'react';
import type { SmartContractMethod } from 'types/api/contract'; import type { SmartContractMethod } from 'types/api/contract';
import infoIcon from 'icons/info.svg'; import Hint from 'ui/shared/Hint';
interface Props<T extends SmartContractMethod> { interface Props<T extends SmartContractMethod> {
data: Array<T>; data: Array<T>;
...@@ -46,32 +46,22 @@ const ContractMethodsAccordion = <T extends SmartContractMethod>({ data, renderC ...@@ -46,32 +46,22 @@ const ContractMethodsAccordion = <T extends SmartContractMethod>({ data, renderC
{ index + 1 }. { item.type === 'fallback' || item.type === 'receive' ? item.type : item.name } { index + 1 }. { item.type === 'fallback' || item.type === 'receive' ? item.type : item.name }
</Box> </Box>
{ item.type === 'fallback' && ( { item.type === 'fallback' && (
<Tooltip <Hint
label={ `The fallback function is executed on a call to the contract if none of the other functions match label={
`The fallback function is executed on a call to the contract if none of the other functions match
the given function signature, or if no data was supplied at all and there is no receive Ether function. the given function signature, or if no data was supplied at all and there is no receive Ether function.
The fallback function always receives data, but in order to also receive Ether it must be marked payable.` } The fallback function always receives data, but in order to also receive Ether it must be marked payable.`
placement="top" }/>
maxW="320px"
>
<Box cursor="pointer" display="inherit">
<Icon as={ infoIcon } boxSize={ 5 }/>
</Box>
</Tooltip>
) } ) }
{ item.type === 'receive' && ( { item.type === 'receive' && (
<Tooltip <Hint
label={ `The receive function is executed on a call to the contract with empty calldata. label={
`The receive function is executed on a call to the contract with empty calldata.
This is the function that is executed on plain Ether transfers (e.g. via .send() or .transfer()). This is the function that is executed on plain Ether transfers (e.g. via .send() or .transfer()).
If no such function exists, but a payable fallback function exists, the fallback function will be called on a plain Ether transfer. If no such function exists, but a payable fallback function exists, the fallback function will be called on a plain Ether transfer.
If neither a receive Ether nor a payable fallback function is present, If neither a receive Ether nor a payable fallback function is present,
the contract cannot receive Ether through regular transactions and throws an exception.` } the contract cannot receive Ether through regular transactions and throws an exception.`
placement="top" }/>
maxW="320px"
>
<Box cursor="pointer" display="inherit">
<Icon as={ infoIcon } boxSize={ 5 }/>
</Box>
</Tooltip>
) } ) }
<AccordionIcon/> <AccordionIcon/>
</AccordionButton> </AccordionButton>
......
import { Box, Flex, Icon, Text, useColorModeValue, chakra, Tooltip, LightMode } from '@chakra-ui/react'; import type { TooltipProps } from '@chakra-ui/react';
import { Flex, Icon, Text, useColorModeValue, chakra, LightMode } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import infoIcon from 'icons/info.svg';
import breakpoints from 'theme/foundations/breakpoints'; import breakpoints from 'theme/foundations/breakpoints';
import Hint from 'ui/shared/Hint';
type Props = { type Props = {
icon: React.FC<React.SVGAttributes<SVGElement>>; icon: React.FC<React.SVGAttributes<SVGElement>>;
...@@ -15,6 +16,14 @@ type Props = { ...@@ -15,6 +16,14 @@ type Props = {
const LARGEST_BREAKPOINT = '1240px'; const LARGEST_BREAKPOINT = '1240px';
const TOOLTIP_PROPS: Partial<TooltipProps> = {
hasArrow: false,
borderRadius: 'md',
placement: 'bottom-end',
offset: [ 0, 0 ],
bgColor: 'blackAlpha.900',
};
const StatsItem = ({ icon, title, value, className, tooltipLabel, url }: Props) => { const StatsItem = ({ icon, title, value, className, tooltipLabel, url }: Props) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
const sxContainer = {} as any; const sxContainer = {} as any;
...@@ -55,20 +64,15 @@ const StatsItem = ({ icon, title, value, className, tooltipLabel, url }: Props) ...@@ -55,20 +64,15 @@ const StatsItem = ({ icon, title, value, className, tooltipLabel, url }: Props)
</Flex> </Flex>
{ tooltipLabel && ( { tooltipLabel && (
<LightMode> <LightMode>
<Tooltip label={ tooltipLabel } hasArrow={ false } borderRadius="12px" placement="bottom-end" offset={ [ 0, 0 ] } bgColor="blackAlpha.900"> <Hint
<Box label={ tooltipLabel }
tooltipProps={ TOOLTIP_PROPS }
boxSize={ 6 }
color={ infoColor }
position="absolute" position="absolute"
top={{ base: 'calc(50% - 12px)', lg: '10px', xl: 'calc(50% - 12px)' }} top={{ base: 'calc(50% - 12px)', lg: '10px', xl: 'calc(50% - 12px)' }}
right="10px" right="10px"
cursor="pointer"
>
<Icon
as={ infoIcon }
boxSize={ 6 }
color={ infoColor }
/> />
</Box>
</Tooltip>
</LightMode> </LightMode>
) } ) }
</Flex> </Flex>
......
import { Box, Flex, Icon, Skeleton, Text, Tooltip, useColorModeValue } from '@chakra-ui/react'; import { Flex, Skeleton, Text, useColorModeValue } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import appConfig from 'configs/app/config'; import appConfig from 'configs/app/config';
import infoIcon from 'icons/info.svg';
import useApiQuery from 'lib/api/useApiQuery'; import useApiQuery from 'lib/api/useApiQuery';
import Hint from 'ui/shared/Hint';
import ChainIndicatorChartContainer from './ChainIndicatorChartContainer'; import ChainIndicatorChartContainer from './ChainIndicatorChartContainer';
import ChainIndicatorItem from './ChainIndicatorItem'; import ChainIndicatorItem from './ChainIndicatorItem';
...@@ -72,13 +72,7 @@ const ChainIndicators = () => { ...@@ -72,13 +72,7 @@ const ChainIndicators = () => {
<Flex flexGrow={ 1 } flexDir="column" order={{ base: 2, lg: 1 }} p={{ base: 6, lg: 0 }}> <Flex flexGrow={ 1 } flexDir="column" order={{ base: 2, lg: 1 }} p={{ base: 6, lg: 0 }}>
<Flex alignItems="center"> <Flex alignItems="center">
<Text fontWeight={ 500 } fontFamily="heading" fontSize="lg">{ indicator?.title }</Text> <Text fontWeight={ 500 } fontFamily="heading" fontSize="lg">{ indicator?.title }</Text>
{ indicator?.hint && ( { indicator?.hint && <Hint label={ indicator.hint } ml={ 1 }/> }
<Tooltip label={ indicator.hint } maxW="300px">
<Box display="inline-flex" cursor="pointer" ml={ 1 }>
<Icon as={ infoIcon } boxSize={ 4 }/>
</Box>
</Tooltip>
) }
</Flex> </Flex>
{ valueTitle } { valueTitle }
<ChainIndicatorChartContainer { ...queryResult }/> <ChainIndicatorChartContainer { ...queryResult }/>
......
import { IconButton, Tooltip, useClipboard, chakra } from '@chakra-ui/react'; import { IconButton, Tooltip, useClipboard, chakra, useDisclosure } from '@chakra-ui/react';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import CopyIcon from 'icons/copy.svg'; import CopyIcon from 'icons/copy.svg';
...@@ -6,6 +6,8 @@ import CopyIcon from 'icons/copy.svg'; ...@@ -6,6 +6,8 @@ import CopyIcon from 'icons/copy.svg';
const CopyToClipboard = ({ text, className }: {text: string; className?: string}) => { const CopyToClipboard = ({ text, className }: {text: string; className?: string}) => {
const { hasCopied, onCopy } = useClipboard(text, 3000); const { hasCopied, onCopy } = useClipboard(text, 3000);
const [ copied, setCopied ] = useState(false); const [ copied, setCopied ] = useState(false);
// have to implement controlled tooltip because of the issue - https://github.com/chakra-ui/chakra-ui/issues/7107
const { isOpen, onOpen, onToggle, onClose } = useDisclosure();
useEffect(() => { useEffect(() => {
if (hasCopied) { if (hasCopied) {
...@@ -15,8 +17,13 @@ const CopyToClipboard = ({ text, className }: {text: string; className?: string} ...@@ -15,8 +17,13 @@ const CopyToClipboard = ({ text, className }: {text: string; className?: string}
} }
}, [ hasCopied ]); }, [ hasCopied ]);
const handleClick = React.useCallback(() => {
onToggle();
onCopy();
}, [ onCopy, onToggle ]);
return ( return (
<Tooltip label={ copied ? 'Copied' : 'Copy to clipboard' } closeOnClick={ false }> <Tooltip label={ copied ? 'Copied' : 'Copy to clipboard' } isOpen={ isOpen }>
<IconButton <IconButton
aria-label="copy" aria-label="copy"
icon={ <CopyIcon/> } icon={ <CopyIcon/> }
...@@ -25,11 +32,13 @@ const CopyToClipboard = ({ text, className }: {text: string; className?: string} ...@@ -25,11 +32,13 @@ const CopyToClipboard = ({ text, className }: {text: string; className?: string}
variant="simple" variant="simple"
display="inline-block" display="inline-block"
flexShrink={ 0 } flexShrink={ 0 }
onClick={ onCopy } onClick={ handleClick }
className={ className } className={ className }
onMouseEnter={ onOpen }
onMouseLeave={ onClose }
/> />
</Tooltip> </Tooltip>
); );
}; };
export default chakra(CopyToClipboard); export default React.memo(chakra(CopyToClipboard));
import { GridItem, Icon, Flex, Tooltip, Box, Text } from '@chakra-ui/react'; import { GridItem, Flex, Text } from '@chakra-ui/react';
import type { HTMLChakraProps } from '@chakra-ui/system'; import type { HTMLChakraProps } from '@chakra-ui/system';
import React from 'react'; import React from 'react';
import infoIcon from 'icons/info.svg'; import Hint from 'ui/shared/Hint';
interface Props extends Omit<HTMLChakraProps<'div'>, 'title'> { interface Props extends Omit<HTMLChakraProps<'div'>, 'title'> {
title: React.ReactNode; title: React.ReactNode;
...@@ -16,15 +16,7 @@ const DetailsInfoItem = ({ title, hint, note, children, id, ...styles }: Props) ...@@ -16,15 +16,7 @@ const DetailsInfoItem = ({ title, hint, note, children, id, ...styles }: Props)
<> <>
<GridItem py={{ base: 1, lg: 2 }} id={ id } lineHeight={ 5 } { ...styles } whiteSpace="nowrap" _notFirst={{ mt: { base: 3, lg: 0 } }}> <GridItem py={{ base: 1, lg: 2 }} id={ id } lineHeight={ 5 } { ...styles } whiteSpace="nowrap" _notFirst={{ mt: { base: 3, lg: 0 } }}>
<Flex columnGap={ 2 } alignItems="flex-start"> <Flex columnGap={ 2 } alignItems="flex-start">
<Tooltip <Hint label={ hint }/>
label={ hint }
placement="top"
maxW="320px"
>
<Box cursor="pointer" display="inherit">
<Icon as={ infoIcon } boxSize={ 5 }/>
</Box>
</Tooltip>
<Text fontWeight={{ base: 700, lg: 500 }}> <Text fontWeight={{ base: 700, lg: 500 }}>
{ title } { title }
{ note && <Text fontWeight={ 500 } variant="secondary" fontSize="xs" className="note" align="right">{ note }</Text> } { note && <Text fontWeight={ 500 } variant="secondary" fontSize="xs" className="note" align="right">{ note }</Text> }
......
import type { TooltipProps } from '@chakra-ui/react';
import { chakra, IconButton, Tooltip, useDisclosure } from '@chakra-ui/react';
import React from 'react';
import InfoIcon from 'icons/info.svg';
interface Props {
label: string | React.ReactNode;
className?: string;
tooltipProps?: Partial<TooltipProps>;
}
const Hint = ({ label, className, tooltipProps }: Props) => {
// have to implement controlled tooltip because of the issue - https://github.com/chakra-ui/chakra-ui/issues/7107
const { isOpen, onOpen, onToggle, onClose } = useDisclosure();
const handleClick = React.useCallback((event: React.MouseEvent) => {
event.stopPropagation();
onToggle();
}, [ onToggle ]);
return (
<Tooltip
label={ label }
placement="top"
maxW="320px"
isOpen={ isOpen }
{ ...tooltipProps }
>
<IconButton
colorScheme="none"
aria-label="hint"
icon={ <InfoIcon/> }
boxSize={ 5 }
variant="simple"
display="inline-block"
flexShrink={ 0 }
className={ className }
onMouseEnter={ onOpen }
onMouseLeave={ onClose }
onClick={ handleClick }
/>
</Tooltip>
);
};
export default React.memo(chakra(Hint));
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