Commit 6aa1b99e authored by tom goriunov's avatar tom goriunov Committed by GitHub

Merge pull request #2700 from blockscout/release/v2-0-1

Release v2.0.1
parents 24eb4fc0 6d44023e
...@@ -17,7 +17,7 @@ NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout ...@@ -17,7 +17,7 @@ NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout
NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}] NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
NEXT_PUBLIC_DATA_AVAILABILITY_ENABLED=true NEXT_PUBLIC_DATA_AVAILABILITY_ENABLED=true
NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swapscout','icon':'swap','dappId':'swapscout'},{'text':'Payment link','icon':'payment_link','dappId':'peanut-protocol'},{'text':'Get gas','icon':'gas','dappId':'smol-refuel'}] NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swapscout','icon':'swap','dappId':'swapscout'},{'text':'Revokescout','icon':'integration/partial','dappId':'revokescout'},{'text':'Payment link','icon':'payment_link','dappId':'peanut-protocol'},{'text':'Get gas','icon':'gas','dappId':'smol-refuel'}]
NEXT_PUBLIC_DEX_POOLS_ENABLED=true NEXT_PUBLIC_DEX_POOLS_ENABLED=true
NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/eth.json NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/eth.json
NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/eth-mainnet.json NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/eth-mainnet.json
...@@ -32,8 +32,8 @@ NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs', 'coin_price', 'market_cap'] ...@@ -32,8 +32,8 @@ NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs', 'coin_price', 'market_cap']
NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
NEXT_PUBLIC_LOGOUT_URL=https://ethereum-mainnet.us.auth0.com/v2/logout NEXT_PUBLIC_LOGOUT_URL=https://ethereum-mainnet.us.auth0.com/v2/logout
NEXT_PUBLIC_MAINTENANCE_ALERT_MESSAGE=<p>Joined recent campaigns? Mint your Merit Badge <a href="https://badges.blockscout.com?utm_source=instance&utm_medium=eth">here</a></p> NEXT_PUBLIC_MAINTENANCE_ALERT_MESSAGE=<p>Joined recent campaigns? Mint your Merit Badge <a href="https://badges.blockscout.com?utm_source=instance&utm_medium=eth">here</a></p>
NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL=https://gist.githubusercontent.com/maikReal/974c47f86a3158c1a86b092ae2f044b3/raw/abcc7e02150cd85d4974503a0357162c0a2c35a9/merits-banner.html NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL=https://gist.githubusercontent.com/0xdeval/b27a4aecaad513fa033e37430a4f9a47/raw/3a2fa70068ea27c3e6d58dc4cdbeb732968d62f3/revokescout-banner.html
NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL=https://swap.blockscout.com?utm_source=blockscout&utm_medium=eth NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL=https://eth.blockscout.com/apps/revokescout?chainId=1
NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=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_ENABLED=true NEXT_PUBLIC_MARKETPLACE_ENABLED=true
NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_BASE_ID=appGkvtmKI7fXE4Vs NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_BASE_ID=appGkvtmKI7fXE4Vs
...@@ -51,7 +51,7 @@ NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH ...@@ -51,7 +51,7 @@ NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Moralis','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/moralis.png','baseUrl':'https://moralis.com/','paths':{'token':'/chain/ethereum/token/price'}},{'title':'GeckoTerminal','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/geckoterminal.png','baseUrl':'https://www.geckoterminal.com/','paths':{'token':'/eth/pools'}},{'title':'Etherscan','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/etherscan.png','baseUrl':'https://etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}, {'title':'Blockchair','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/blockchair.png','baseUrl':'https://blockchair.com/','paths':{'tx':'/ethereum/transaction','address':'/ethereum/address','token':'/ethereum/erc-20/token','block':'/ethereum/block'}},{'title':'Sentio','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/sentio.png','baseUrl':'https://app.sentio.xyz/','paths':{'tx':'/tx/1','address':'/contract/1'}}, {'title':'Tenderly','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/tenderly.png','baseUrl':'https://dashboard.tenderly.co','paths':{'tx':'/tx/mainnet'}}, {'title':'0xPPL','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/0xPPL.png','baseUrl':'https://0xppl.com','paths':{'tx':'/Ethereum/tx','address':'/','token':'/c/Ethereum'}}, {'title':'3xpl','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/3xpl.png','baseUrl':'https://3xpl.com/','paths':{'tx':'/ethereum/transaction','address':'/ethereum/address'}} ] NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Moralis','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/moralis.png','baseUrl':'https://moralis.com/','paths':{'token':'/chain/ethereum/token/price'}},{'title':'GeckoTerminal','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/geckoterminal.png','baseUrl':'https://www.geckoterminal.com/','paths':{'token':'/eth/pools'}},{'title':'Etherscan','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/etherscan.png','baseUrl':'https://etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}, {'title':'Blockchair','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/blockchair.png','baseUrl':'https://blockchair.com/','paths':{'tx':'/ethereum/transaction','address':'/ethereum/address','token':'/ethereum/erc-20/token','block':'/ethereum/block'}},{'title':'Sentio','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/sentio.png','baseUrl':'https://app.sentio.xyz/','paths':{'tx':'/tx/1','address':'/contract/1'}}, {'title':'Tenderly','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/tenderly.png','baseUrl':'https://dashboard.tenderly.co','paths':{'tx':'/tx/mainnet'}}, {'title':'0xPPL','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/0xPPL.png','baseUrl':'https://0xppl.com','paths':{'tx':'/Ethereum/tx','address':'/','token':'/c/Ethereum'}}, {'title':'3xpl','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/3xpl.png','baseUrl':'https://3xpl.com/','paths':{'tx':'/ethereum/transaction','address':'/ethereum/address'}} ]
NEXT_PUBLIC_NETWORK_ID=1 NEXT_PUBLIC_NETWORK_ID=1
NEXT_PUBLIC_NETWORK_NAME=Ethereum NEXT_PUBLIC_NETWORK_NAME=Ethereum
NEXT_PUBLIC_NETWORK_RPC_URL=https://eth.drpc.org NEXT_PUBLIC_NETWORK_RPC_URL=https://rpc.eth.gateway.fm
NEXT_PUBLIC_NETWORK_SHORT_NAME=Ethereum NEXT_PUBLIC_NETWORK_SHORT_NAME=Ethereum
NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE=validation NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE=validation
NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true
...@@ -60,10 +60,11 @@ NEXT_PUBLIC_OTHER_LINKS=[{'url':'https://eth.drpc.org?ref=559183','text':'Public ...@@ -60,10 +60,11 @@ NEXT_PUBLIC_OTHER_LINKS=[{'url':'https://eth.drpc.org?ref=559183','text':'Public
NEXT_PUBLIC_REWARDS_SERVICE_API_HOST=https://merits.blockscout.com NEXT_PUBLIC_REWARDS_SERVICE_API_HOST=https://merits.blockscout.com
NEXT_PUBLIC_SAFE_TX_SERVICE_URL=https://safe-transaction-mainnet.safe.global NEXT_PUBLIC_SAFE_TX_SERVICE_URL=https://safe-transaction-mainnet.safe.global
NEXT_PUBLIC_SAVE_ON_GAS_ENABLED=true NEXT_PUBLIC_SAVE_ON_GAS_ENABLED=true
NEXT_PUBLIC_STATS_API_HOST=https://stats-eth-main.k8s-prod-1.blockscout.com NEXT_PUBLIC_STATS_API_BASE_PATH=/stats-service
NEXT_PUBLIC_STATS_API_HOST=https://eth.blockscout.com
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES=[{'name':'Rarible','collection_url':'https://rarible.com/collection/{hash}/items','instance_url':'https://rarible.com/token/{hash}:{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/rarible.png'},{'name':'Blur','collection_url':'https://blur.io/eth/collection/{hash}','instance_url':'https://blur.io/eth/asset/{hash}/{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/blur.png'},{'name':'Nftrade','collection_url':'https://nftrade.com/assets/eth/{hash}','instance_url':'https://nftrade.com/assets/eth/{hash}/{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/nftrade.png'},{'name':'MagicEden','collection_url':'https://magiceden.io/collections/ethereum/{hash}','instance_url':'https://magiceden.io/item-details/ethereum/{hash}/{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/magiceden.png'}] NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES=[{'name':'OpenSea','collection_url':'https://opensea.io/assets/ethereum/{hash}','instance_url':'https://opensea.io/assets/ethereum/{hash}/{id}','logo_url':'https://opensea.io/static/images/logos/opensea-logo.svg'},{'name':'Rarible','collection_url':'https://rarible.com/collection/{hash}/items','instance_url':'https://rarible.com/token/{hash}:{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/rarible.png'},{'name':'Blur','collection_url':'https://blur.io/eth/collection/{hash}','instance_url':'https://blur.io/eth/asset/{hash}/{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/blur.png'},{'name':'MagicEden','collection_url':'https://magiceden.io/collections/ethereum/{hash}','instance_url':'https://magiceden.io/item-details/ethereum/{hash}/{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/magiceden.png'}]
NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true NEXT_PUBLIC_VIEWS_TOKEN_SCAM_TOGGLE_ENABLED=true
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
NEXT_PUBLIC_XSTAR_SCORE_URL=https://docs.xname.app/the-solution-adaptive-proof-of-humanity-on-blockchain/xhs-scoring-algorithm?utm_source=blockscout&utm_medium=address NEXT_PUBLIC_XSTAR_SCORE_URL=https://docs.xname.app/the-solution-adaptive-proof-of-humanity-on-blockchain/xhs-scoring-algorithm?utm_source=blockscout&utm_medium=address
\ No newline at end of file
...@@ -46,6 +46,19 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>( ...@@ -46,6 +46,19 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const handleOpenChange = React.useCallback((details: { open: boolean }) => {
setOpen(details.open);
onOpenChange?.(details);
}, [ onOpenChange ]);
const handleOpenChangeManual = React.useCallback((nextOpen: boolean) => {
timeoutRef.current && window.clearTimeout(timeoutRef.current);
timeoutRef.current = window.setTimeout(() => {
setOpen(nextOpen);
onOpenChange?.({ open: nextOpen });
}, nextOpen ? openDelay : closeDelay);
}, [ closeDelay, openDelay, onOpenChange ]);
const handleClickAway = React.useCallback((event: Event) => { const handleClickAway = React.useCallback((event: Event) => {
if (interactive) { if (interactive) {
const closest = (event.target as HTMLElement)?.closest('.chakra-tooltip__positioner'); const closest = (event.target as HTMLElement)?.closest('.chakra-tooltip__positioner');
...@@ -54,29 +67,27 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>( ...@@ -54,29 +67,27 @@ export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>(
} }
} }
timeoutRef.current = window.setTimeout(() => { handleOpenChangeManual(false);
setOpen(false); }, [ interactive, handleOpenChangeManual ]);
}, closeDelay);
}, [ closeDelay, interactive ]);
const triggerRef = useClickAway<HTMLButtonElement>(handleClickAway);
const handleOpenChange = React.useCallback((details: { open: boolean }) => { const triggerRef = useClickAway<HTMLButtonElement>(handleClickAway);
setOpen(details.open);
onOpenChange?.(details);
}, [ onOpenChange ]);
const handleTriggerClick = React.useCallback(() => { const handleTriggerClick = React.useCallback(() => {
if (timeoutRef.current) { handleOpenChangeManual(!open);
window.clearTimeout(timeoutRef.current); }, [ handleOpenChangeManual, open ]);
}
timeoutRef.current = window.setTimeout(() => {
setOpen((prev) => !prev);
}, open ? closeDelay : openDelay);
}, [ open, openDelay, closeDelay ]);
const handleContentClick = React.useCallback((event: React.MouseEvent<HTMLDivElement>) => { const handleContentClick = React.useCallback((event: React.MouseEvent<HTMLDivElement>) => {
// otherwise, the event will be propagated to the trigger
// and if the trigger is a link, navigation will be triggered
event.stopPropagation(); event.stopPropagation();
}, []);
if (interactive) {
const closestLink = (event.target as HTMLElement)?.closest('a');
if (closestLink) {
handleOpenChangeManual(false);
}
}
}, [ interactive, handleOpenChangeManual ]);
React.useEffect(() => { React.useEffect(() => {
return () => { return () => {
......
...@@ -162,7 +162,7 @@ export const recipe = defineSlotRecipe({ ...@@ -162,7 +162,7 @@ export const recipe = defineSlotRecipe({
full: { full: {
content: { content: {
maxW: '100vw', maxW: '100vw',
minH: '100vh', minH: '100dvh',
'--dialog-margin': '0', '--dialog-margin': '0',
borderRadius: '0', borderRadius: '0',
}, },
......
...@@ -116,7 +116,6 @@ const AddressBlocksValidated = ({ shouldRender = true, isQueryEnabled = true }: ...@@ -116,7 +116,6 @@ const AddressBlocksValidated = ({ shouldRender = true, isQueryEnabled = true }:
</TableHeaderSticky> </TableHeaderSticky>
<TableBody> <TableBody>
<SocketNewItemsNotice.Desktop <SocketNewItemsNotice.Desktop
url={ window.location.href }
num={ newItemsCount } num={ newItemsCount }
alert={ socketAlert } alert={ socketAlert }
type="block" type="block"
...@@ -136,7 +135,6 @@ const AddressBlocksValidated = ({ shouldRender = true, isQueryEnabled = true }: ...@@ -136,7 +135,6 @@ const AddressBlocksValidated = ({ shouldRender = true, isQueryEnabled = true }:
<Box hideFrom="lg"> <Box hideFrom="lg">
{ query.pagination.page === 1 && ( { query.pagination.page === 1 && (
<SocketNewItemsNotice.Mobile <SocketNewItemsNotice.Mobile
url={ window.location.href }
num={ newItemsCount } num={ newItemsCount }
alert={ socketAlert } alert={ socketAlert }
type="block" type="block"
......
...@@ -197,7 +197,6 @@ const AddressTokenTransfers = ({ overloadCount = OVERLOAD_COUNT, shouldRender = ...@@ -197,7 +197,6 @@ const AddressTokenTransfers = ({ overloadCount = OVERLOAD_COUNT, shouldRender =
<Box hideFrom="lg"> <Box hideFrom="lg">
{ pagination.page === 1 && ( { pagination.page === 1 && (
<SocketNewItemsNotice.Mobile <SocketNewItemsNotice.Mobile
url={ window.location.href }
num={ newItemsCount } num={ newItemsCount }
alert={ socketAlert } alert={ socketAlert }
type="token_transfer" type="token_transfer"
......
...@@ -17,7 +17,7 @@ const ContractMethodAddressButton = ({ onClick, isDisabled }: Props) => { ...@@ -17,7 +17,7 @@ const ContractMethodAddressButton = ({ onClick, isDisabled }: Props) => {
}, [ address, onClick ]); }, [ address, onClick ]);
return ( return (
<Tooltip content="Connect your wallet to enter your address." disabled={ Boolean(address) }> <Tooltip content="Connect your wallet to enter your address." disabled={ Boolean(address) } disableOnMobile>
<Button <Button
variant="subtle" variant="subtle"
size="xs" size="xs"
......
...@@ -73,7 +73,7 @@ const AddressBalance = ({ data, isLoading }: Props) => { ...@@ -73,7 +73,7 @@ const AddressBalance = ({ data, isLoading }: Props) => {
> >
Balance Balance
</DetailedInfo.ItemLabel> </DetailedInfo.ItemLabel>
<DetailedInfo.ItemValue alignSelf="center" flexWrap="nowrap"> <DetailedInfo.ItemValue alignSelf="flex-start" flexWrap="nowrap">
<NativeTokenIcon boxSize={ 6 } mr={ 2 } isLoading={ isLoading }/> <NativeTokenIcon boxSize={ 6 } mr={ 2 } isLoading={ isLoading }/>
<CurrencyValue <CurrencyValue
value={ data.coin_balance || '0' } value={ data.coin_balance || '0' }
......
...@@ -60,7 +60,7 @@ const AddressFavoriteButton = ({ className, hash, watchListId }: Props) => { ...@@ -60,7 +60,7 @@ const AddressFavoriteButton = ({ className, hash, watchListId }: Props) => {
<> <>
<AuthGuard onAuthSuccess={ handleAddToFavorite }> <AuthGuard onAuthSuccess={ handleAddToFavorite }>
{ ({ onClick }) => ( { ({ onClick }) => (
<Tooltip content={ `${ watchListId ? 'Remove address from Watch list' : 'Add address to Watch list' }` }> <Tooltip content={ `${ watchListId ? 'Remove address from Watch list' : 'Add address to Watch list' }` } disableOnMobile>
<IconButton <IconButton
className={ className } className={ className }
aria-label="edit" aria-label="edit"
......
...@@ -58,7 +58,7 @@ const AddressQrCode = ({ hash, className, isLoading }: Props) => { ...@@ -58,7 +58,7 @@ const AddressQrCode = ({ hash, className, isLoading }: Props) => {
return ( return (
<> <>
<Tooltip content="Click to view QR code"> <Tooltip content="Click to view QR code" disableOnMobile>
<IconButton <IconButton
className={ className } className={ className }
aria-label="Show QR code" aria-label="Show QR code"
......
...@@ -83,7 +83,7 @@ const AddressEnsDomains = ({ query, addressHash, mainDomainName }: Props) => { ...@@ -83,7 +83,7 @@ const AddressEnsDomains = ({ query, addressHash, mainDomainName }: Props) => {
return ( return (
<PopoverRoot> <PopoverRoot>
<Tooltip content="List of names resolved or owned by this address"> <Tooltip content="List of names resolved or owned by this address" disableOnMobile>
<div> <div>
<PopoverTrigger> <PopoverTrigger>
<Button <Button
......
...@@ -90,7 +90,6 @@ const BlocksContent = ({ type, query, enableSocket = true, top }: Props) => { ...@@ -90,7 +90,6 @@ const BlocksContent = ({ type, query, enableSocket = true, top }: Props) => {
<Box hideFrom="lg"> <Box hideFrom="lg">
{ query.pagination.page === 1 && enableSocket && ( { query.pagination.page === 1 && enableSocket && (
<SocketNewItemsNotice.Mobile <SocketNewItemsNotice.Mobile
url={ window.location.href }
num={ newItemsCount } num={ newItemsCount }
alert={ socketAlert } alert={ socketAlert }
type="block" type="block"
......
...@@ -67,7 +67,6 @@ const BlocksTable = ({ data, isLoading, top, page, showSocketInfo, socketInfoNum ...@@ -67,7 +67,6 @@ const BlocksTable = ({ data, isLoading, top, page, showSocketInfo, socketInfoNum
<TableBody> <TableBody>
{ showSocketInfo && ( { showSocketInfo && (
<SocketNewItemsNotice.Desktop <SocketNewItemsNotice.Desktop
url={ window.location.href }
alert={ socketInfoAlert } alert={ socketInfoAlert }
num={ socketInfoNum } num={ socketInfoNum }
type="block" type="block"
......
...@@ -11,8 +11,6 @@ const test = base.extend<{ context: BrowserContext }>({ ...@@ -11,8 +11,6 @@ const test = base.extend<{ context: BrowserContext }>({
context: contextWithAuth, context: contextWithAuth,
}); });
test.use({ viewport: { width: 200, height: 200 } });
test.describe('with multiple items', () => { test.describe('with multiple items', () => {
const hooksConfig = { const hooksConfig = {
router: { router: {
...@@ -30,14 +28,14 @@ test.describe('with multiple items', () => { ...@@ -30,14 +28,14 @@ test.describe('with multiple items', () => {
const component = await render(<AccountActionsMenu/>, { hooksConfig }); const component = await render(<AccountActionsMenu/>, { hooksConfig });
await component.getByRole('button').click(); await component.getByRole('button').click();
await expect(page).toHaveScreenshot(); await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 200, height: 200 } });
}); });
test('base view with styles', async({ render, page }) => { test('base view with styles', async({ render, page }) => {
const component = await render(<AccountActionsMenu m={ 2 } outline="1px solid lightpink"/>, { hooksConfig }); const component = await render(<AccountActionsMenu m={ 2 } outline="1px solid lightpink"/>, { hooksConfig });
await component.getByRole('button').click(); await component.getByRole('button').click();
await expect(page).toHaveScreenshot(); await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 200, height: 200 } });
}); });
test('loading', async({ render }) => { test('loading', async({ render }) => {
...@@ -65,15 +63,15 @@ test.describe('with one item', () => { ...@@ -65,15 +63,15 @@ test.describe('with one item', () => {
test('base view', async({ render, page }) => { test('base view', async({ render, page }) => {
const component = await render(<AccountActionsMenu/>, { hooksConfig }); const component = await render(<AccountActionsMenu/>, { hooksConfig });
await component.getByRole('button').hover(); await component.getByRole('button').hover();
await expect(page.getByText('Add private tag')).toBeVisible();
await expect(page).toHaveScreenshot(); await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 200, height: 200 } });
}); });
test('base view with styles', async({ render, page }) => { test('base view with styles', async({ render, page }) => {
const component = await render(<AccountActionsMenu m={ 2 } outline="1px solid lightpink"/>, { hooksConfig }); const component = await render(<AccountActionsMenu m={ 2 } outline="1px solid lightpink"/>, { hooksConfig });
await component.getByRole('button').hover(); await component.getByRole('button').hover();
await expect(page.getByText('Add private tag')).toBeVisible();
await expect(page).toHaveScreenshot(); await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 200, height: 200 } });
}); });
test('loading', async({ render }) => { test('loading', async({ render }) => {
......
...@@ -15,7 +15,7 @@ interface Props { ...@@ -15,7 +15,7 @@ interface Props {
const ButtonItem = ({ className, label, onClick, icon, isDisabled }: Props) => { const ButtonItem = ({ className, label, onClick, icon, isDisabled }: Props) => {
return ( return (
<Tooltip content={ label } disabled={ isDisabled }> <Tooltip content={ label } disabled={ isDisabled } disableOnMobile>
<IconButton <IconButton
aria-label={ label } aria-label={ label }
className={ className } className={ className }
......
...@@ -14,13 +14,17 @@ interface Props { ...@@ -14,13 +14,17 @@ interface Props {
type?: 'transaction' | 'token_transfer' | 'deposit' | 'block'; type?: 'transaction' | 'token_transfer' | 'deposit' | 'block';
children?: (props: InjectedProps) => React.JSX.Element; children?: (props: InjectedProps) => React.JSX.Element;
className?: string; className?: string;
url: string; url?: string;
alert?: string; alert?: string;
num?: number; num?: number;
isLoading?: boolean; isLoading?: boolean;
} }
const SocketNewItemsNotice = chakra(({ children, className, url, num, alert, type = 'transaction', isLoading }: Props) => { const SocketNewItemsNotice = chakra(({ children, className, url, num, alert, type = 'transaction', isLoading }: Props) => {
const handleLinkClick = React.useCallback(() => {
window.location.reload();
}, []);
const alertContent = (() => { const alertContent = (() => {
if (alert) { if (alert) {
return alert; return alert;
...@@ -49,7 +53,7 @@ const SocketNewItemsNotice = chakra(({ children, className, url, num, alert, typ ...@@ -49,7 +53,7 @@ const SocketNewItemsNotice = chakra(({ children, className, url, num, alert, typ
return ( return (
<> <>
<Link href={ url }>{ num.toLocaleString() } more { name }{ num > 1 ? 's' : '' }</Link> <Link href={ url } onClick={ !url ? handleLinkClick : undefined }>{ num.toLocaleString() } more { name }{ num > 1 ? 's' : '' }</Link>
<Text whiteSpace="pre"> ha{ num > 1 ? 've' : 's' } come in</Text> <Text whiteSpace="pre"> ha{ num > 1 ? 've' : 's' } come in</Text>
</> </>
); );
......
...@@ -17,7 +17,7 @@ const TableItemActionButtons = ({ onEditClick, onDeleteClick, isLoading }: Props ...@@ -17,7 +17,7 @@ const TableItemActionButtons = ({ onEditClick, onDeleteClick, isLoading }: Props
return ( return (
<HStack gap={ 6 } alignSelf="flex-end"> <HStack gap={ 6 } alignSelf="flex-end">
<Tooltip content="Edit"> <Tooltip content="Edit" disableOnMobile>
<IconButton <IconButton
aria-label="edit" aria-label="edit"
variant="link" variant="link"
...@@ -30,7 +30,7 @@ const TableItemActionButtons = ({ onEditClick, onDeleteClick, isLoading }: Props ...@@ -30,7 +30,7 @@ const TableItemActionButtons = ({ onEditClick, onDeleteClick, isLoading }: Props
<IconSvg name="edit"/> <IconSvg name="edit"/>
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Tooltip content="Delete"> <Tooltip content="Delete" disableOnMobile>
<IconButton <IconButton
aria-label="delete" aria-label="delete"
variant="link" variant="link"
......
...@@ -47,7 +47,6 @@ const TokenTransferTable = ({ ...@@ -47,7 +47,6 @@ const TokenTransferTable = ({
<TableBody> <TableBody>
{ showSocketInfo && ( { showSocketInfo && (
<SocketNewItemsNotice.Desktop <SocketNewItemsNotice.Desktop
url={ window.location.href }
alert={ socketInfoAlert } alert={ socketInfoAlert }
num={ socketInfoNum } num={ socketInfoNum }
type="token_transfer" type="token_transfer"
......
...@@ -27,6 +27,7 @@ const Icon = (props: EntityBase.IconBaseProps) => { ...@@ -27,6 +27,7 @@ const Icon = (props: EntityBase.IconBaseProps) => {
<EntityBase.Icon <EntityBase.Icon
{ ...props } { ...props }
name={ props.name ?? 'blob' } name={ props.name ?? 'blob' }
borderRadius={ props.isLoading ? 'sm' : 'none' }
/> />
); );
}; };
......
...@@ -7,6 +7,9 @@ import HeaderMobile from 'ui/snippets/header/HeaderMobile'; ...@@ -7,6 +7,9 @@ import HeaderMobile from 'ui/snippets/header/HeaderMobile';
import * as Layout from './components'; import * as Layout from './components';
const TOP_BAR_HEIGHT = 36;
const HEADER_HEIGHT_MOBILE = 56;
const LayoutDefault = ({ children }: Props) => { const LayoutDefault = ({ children }: Props) => {
return ( return (
<Layout.Container <Layout.Container
...@@ -17,7 +20,13 @@ const LayoutDefault = ({ children }: Props) => { ...@@ -17,7 +20,13 @@ const LayoutDefault = ({ children }: Props) => {
> >
<Layout.TopRow/> <Layout.TopRow/>
<HeaderMobile hideSearchBar/> <HeaderMobile hideSearchBar/>
<Layout.MainArea minH="auto" flex={ 1 }> <Layout.MainArea
minH={{
base: `calc(100dvh - ${ TOP_BAR_HEIGHT + HEADER_HEIGHT_MOBILE }px)`,
lg: `calc(100dvh - ${ TOP_BAR_HEIGHT }px)`,
}}
flex={ 1 }
>
<Layout.MainColumn <Layout.MainColumn
paddingTop={{ base: 0, lg: 0 }} paddingTop={{ base: 0, lg: 0 }}
paddingBottom={ 0 } paddingBottom={ 0 }
......
...@@ -64,6 +64,7 @@ const StatsWidget = ({ ...@@ -64,6 +64,7 @@ const StatsWidget = ({
justifyContent="space-between" justifyContent="space-between"
columnGap={ 2 } columnGap={ 2 }
w="100%" w="100%"
h="100%"
> >
{ icon && ( { icon && (
<IconSvg <IconSvg
......
...@@ -76,7 +76,6 @@ const AlertShowcase = () => { ...@@ -76,7 +76,6 @@ const AlertShowcase = () => {
</TableHeader> </TableHeader>
<TableBody> <TableBody>
<SocketNewItemsNotice.Desktop <SocketNewItemsNotice.Desktop
url={ window.location.href }
num={ 1234 } num={ 1234 }
type="block" type="block"
isLoading isLoading
...@@ -95,7 +94,6 @@ const AlertShowcase = () => { ...@@ -95,7 +94,6 @@ const AlertShowcase = () => {
</TableHeader> </TableHeader>
<TableBody> <TableBody>
<SocketNewItemsNotice.Desktop <SocketNewItemsNotice.Desktop
url={ window.location.href }
num={ 1234 } num={ 1234 }
type="block" type="block"
isLoading={ false } isLoading={ false }
......
...@@ -74,6 +74,7 @@ const UserProfileButton = ({ profileQuery, size, variant, onClick, isPending, .. ...@@ -74,6 +74,7 @@ const UserProfileButton = ({ profileQuery, size, variant, onClick, isPending, ..
content={ <span>Sign in to My Account to add tags,<br/>create watchlists, access API keys and more</span> } content={ <span>Sign in to My Account to add tags,<br/>create watchlists, access API keys and more</span> }
disabled={ isMobile || isLoading || Boolean(data) } disabled={ isMobile || isLoading || Boolean(data) }
openDelay={ 500 } openDelay={ 500 }
disableOnMobile
> >
<span> <span>
<Button <Button
......
...@@ -42,6 +42,7 @@ const UserWalletButton = ({ size, variant, isPending, isAutoConnectDisabled, add ...@@ -42,6 +42,7 @@ const UserWalletButton = ({ size, variant, isPending, isAutoConnectDisabled, add
content={ <span>Connect your wallet<br/>to Blockscout for<br/>full-featured access</span> } content={ <span>Connect your wallet<br/>to Blockscout for<br/>full-featured access</span> }
disabled={ isMobile || Boolean(address) } disabled={ isMobile || Boolean(address) }
openDelay={ 500 } openDelay={ 500 }
disableOnMobile
> >
<Button <Button
ref={ ref } ref={ ref }
......
...@@ -67,12 +67,12 @@ const ChartsWidgetsList = ({ filterQuery, isError, isPlaceholderData, charts, in ...@@ -67,12 +67,12 @@ const ChartsWidgetsList = ({ filterQuery, isError, isPlaceholderData, charts, in
charts?.map((section) => ( charts?.map((section) => (
<Box <Box
key={ section.id } key={ section.id }
mb={ 8 } mb={{ base: 6, lg: 8 }}
_last={{ _last={{
marginBottom: 0, marginBottom: 0,
}} }}
> >
<Skeleton loading={ isPlaceholderData } mb={ 4 } display="inline-flex" alignItems="center" columnGap={ 2 } id={ section.id }> <Skeleton loading={ isPlaceholderData } mb={{ base: 3, lg: 4 }} display="inline-flex" alignItems="center" columnGap={ 2 } id={ section.id }>
<Heading level="2" id={ section.id }> <Heading level="2" id={ section.id }>
{ section.title } { section.title }
</Heading> </Heading>
...@@ -85,7 +85,7 @@ const ChartsWidgetsList = ({ filterQuery, isError, isPlaceholderData, charts, in ...@@ -85,7 +85,7 @@ const ChartsWidgetsList = ({ filterQuery, isError, isPlaceholderData, charts, in
<Grid <Grid
templateColumns={{ lg: 'repeat(2, minmax(0, 1fr))' }} templateColumns={{ lg: 'repeat(2, minmax(0, 1fr))' }}
gap={ 4 } gap={{ base: 3, lg: 4 }}
> >
{ section.charts.map((chart) => ( { section.charts.map((chart) => (
<ChartWidgetContainer <ChartWidgetContainer
......
...@@ -23,7 +23,7 @@ const NumberWidgetsList = () => { ...@@ -23,7 +23,7 @@ const NumberWidgetsList = () => {
return ( return (
<Grid <Grid
gridTemplateColumns={{ base: 'repeat(2, 1fr)', lg: 'repeat(4, 1fr)' }} gridTemplateColumns={{ base: 'repeat(2, 1fr)', lg: 'repeat(4, 1fr)' }}
gridGap={ 4 } gridGap={{ base: 1, lg: 2 }}
> >
{ {
data?.counters?.map(({ id, title, value, units, description }, index) => { data?.counters?.map(({ id, title, value, units, description }, index) => {
......
...@@ -89,7 +89,6 @@ const TokenTransfer = ({ transfersQuery, tokenId, tokenQuery, tabsHeight = TABS_ ...@@ -89,7 +89,6 @@ const TokenTransfer = ({ transfersQuery, tokenId, tokenQuery, tabsHeight = TABS_
<Box display={{ base: 'block', lg: 'none' }}> <Box display={{ base: 'block', lg: 'none' }}>
{ pagination.page === 1 && ( { pagination.page === 1 && (
<SocketNewItemsNotice.Mobile <SocketNewItemsNotice.Mobile
url={ window.location.href }
num={ newItemsCount } num={ newItemsCount }
alert={ socketAlert } alert={ socketAlert }
type="token_transfer" type="token_transfer"
......
...@@ -47,7 +47,6 @@ const TokenTransferTable = ({ data, top, showSocketInfo, socketInfoAlert, socket ...@@ -47,7 +47,6 @@ const TokenTransferTable = ({ data, top, showSocketInfo, socketInfoAlert, socket
<TableBody> <TableBody>
{ showSocketInfo && ( { showSocketInfo && (
<SocketNewItemsNotice.Desktop <SocketNewItemsNotice.Desktop
url={ window.location.href }
alert={ socketInfoAlert } alert={ socketInfoAlert }
num={ socketInfoNum } num={ socketInfoNum }
type="token_transfer" type="token_transfer"
......
...@@ -141,7 +141,7 @@ const TxSubHeading = ({ hash, hasTag, txQuery }: Props) => { ...@@ -141,7 +141,7 @@ const TxSubHeading = ({ hash, hasTag, txQuery }: Props) => {
{ appActionData && ( { appActionData && (
<AppActionButton data={ appActionData } txHash={ hash } source="Txn"/> <AppActionButton data={ appActionData } txHash={ hash } source="Txn"/>
) } ) }
<NetworkExplorers type="tx" pathParam={ hash } ml={{ base: 0, lg: 'auto' }}/> <NetworkExplorers type="tx" pathParam={ hash } ml="auto"/>
</Flex> </Flex>
</Box> </Box>
); );
......
...@@ -21,7 +21,6 @@ const TxsSocketNoticeTypeAddress = ({ place, isLoading }: Props) => { ...@@ -21,7 +21,6 @@ const TxsSocketNoticeTypeAddress = ({ place, isLoading }: Props) => {
if (place === 'table') { if (place === 'table') {
return ( return (
<SocketNewItemsNotice.Desktop <SocketNewItemsNotice.Desktop
url={ window.location.href }
alert={ alertText } alert={ alertText }
num={ num } num={ num }
isLoading={ isLoading } isLoading={ isLoading }
...@@ -32,7 +31,6 @@ const TxsSocketNoticeTypeAddress = ({ place, isLoading }: Props) => { ...@@ -32,7 +31,6 @@ const TxsSocketNoticeTypeAddress = ({ place, isLoading }: Props) => {
if (place === 'list') { if (place === 'list') {
return ( return (
<SocketNewItemsNotice.Mobile <SocketNewItemsNotice.Mobile
url={ window.location.href }
num={ num } num={ num }
alert={ alertText } alert={ alertText }
isLoading={ isLoading } isLoading={ isLoading }
......
...@@ -22,7 +22,6 @@ const TxsSocketNoticeTypeAll = ({ type, place, isLoading }: Props) => { ...@@ -22,7 +22,6 @@ const TxsSocketNoticeTypeAll = ({ type, place, isLoading }: Props) => {
if (place === 'table') { if (place === 'table') {
return ( return (
<SocketNewItemsNotice.Desktop <SocketNewItemsNotice.Desktop
url={ window.location.href }
alert={ alertText } alert={ alertText }
num={ num } num={ num }
isLoading={ isLoading } isLoading={ isLoading }
...@@ -33,7 +32,6 @@ const TxsSocketNoticeTypeAll = ({ type, place, isLoading }: Props) => { ...@@ -33,7 +32,6 @@ const TxsSocketNoticeTypeAll = ({ type, place, isLoading }: Props) => {
if (place === 'list') { if (place === 'list') {
return ( return (
<SocketNewItemsNotice.Mobile <SocketNewItemsNotice.Mobile
url={ window.location.href }
num={ num } num={ num }
alert={ alertText } alert={ alertText }
isLoading={ isLoading } isLoading={ isLoading }
......
...@@ -25,6 +25,7 @@ const UserOpDecodedCallData = ({ data }: Props) => { ...@@ -25,6 +25,7 @@ const UserOpDecodedCallData = ({ data }: Props) => {
const toggler = data.call_data && data.execute_call_data ? ( const toggler = data.call_data && data.execute_call_data ? (
<UserOpCallDataSwitch <UserOpCallDataSwitch
id="call-data-switch"
onChange={ handleSwitchChange } onChange={ handleSwitchChange }
initialValue={ false } initialValue={ false }
ml={{ base: 3, lg: 'auto' }} ml={{ base: 3, lg: 'auto' }}
......
...@@ -5,13 +5,14 @@ import { Switch } from 'toolkit/chakra/switch'; ...@@ -5,13 +5,14 @@ import { Switch } from 'toolkit/chakra/switch';
import { Hint } from 'toolkit/components/Hint/Hint'; import { Hint } from 'toolkit/components/Hint/Hint';
interface Props { interface Props {
id: string;
onChange: (isChecked: boolean) => void; onChange: (isChecked: boolean) => void;
initialValue?: boolean; initialValue?: boolean;
isDisabled?: boolean; isDisabled?: boolean;
className?: string; className?: string;
} }
const UserOpCallDataSwitch = ({ className, initialValue, isDisabled, onChange }: Props) => { const UserOpCallDataSwitch = ({ className, initialValue, isDisabled, onChange, id }: Props) => {
const [ isChecked, setIsChecked ] = React.useState(initialValue ?? false); const [ isChecked, setIsChecked ] = React.useState(initialValue ?? false);
const handleChange = React.useCallback(() => { const handleChange = React.useCallback(() => {
...@@ -26,7 +27,7 @@ const UserOpCallDataSwitch = ({ className, initialValue, isDisabled, onChange }: ...@@ -26,7 +27,7 @@ const UserOpCallDataSwitch = ({ className, initialValue, isDisabled, onChange }:
<Flex ml="auto" alignItems="center" gap={ 2 }> <Flex ml="auto" alignItems="center" gap={ 2 }>
<Switch <Switch
className={ className } className={ className }
id="call-data-switch" id={ id }
checked={ isChecked } checked={ isChecked }
disabled={ isDisabled } disabled={ isDisabled }
onCheckedChange={ handleChange } onCheckedChange={ handleChange }
......
...@@ -25,6 +25,7 @@ const UserOpDecodedCallData = ({ data }: Props) => { ...@@ -25,6 +25,7 @@ const UserOpDecodedCallData = ({ data }: Props) => {
const toggler = data.decoded_call_data && data.decoded_execute_call_data ? ( const toggler = data.decoded_call_data && data.decoded_execute_call_data ? (
<UserOpCallDataSwitch <UserOpCallDataSwitch
id="decoded-call-data-switch"
onChange={ handleSwitchChange } onChange={ handleSwitchChange }
initialValue={ false } initialValue={ false }
ml={{ base: 0, lg: 'auto' }} ml={{ base: 0, lg: 'auto' }}
......
...@@ -66,7 +66,7 @@ const VerifiedAddressesListItem = ({ item, application, onAdd, onEdit, isLoading ...@@ -66,7 +66,7 @@ const VerifiedAddressesListItem = ({ item, application, onAdd, onEdit, isLoading
noCopy noCopy
noSymbol noSymbol
/> />
<Tooltip content="Edit" disabled={ isLoading }> <Tooltip content="Edit" disabled={ isLoading } disableOnMobile>
<IconButton <IconButton
aria-label="edit" aria-label="edit"
variant="link" variant="link"
......
...@@ -83,7 +83,7 @@ const VerifiedAddressesTableItem = ({ item, application, onAdd, onEdit, isLoadin ...@@ -83,7 +83,7 @@ const VerifiedAddressesTableItem = ({ item, application, onAdd, onEdit, isLoadin
</TableCell> </TableCell>
<TableCell pl="0"> <TableCell pl="0">
{ item.metadata.tokenName && application && !isLoading ? ( { item.metadata.tokenName && application && !isLoading ? (
<Tooltip content="Edit" disabled={ isLoading }> <Tooltip content="Edit" disabled={ isLoading } disableOnMobile>
<IconButton <IconButton
aria-label="edit" aria-label="edit"
variant="link" variant="link"
......
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