Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions toolkit/chakra/image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import { Skeleton } from './skeleton';

export interface ImageProps extends ChakraImageProps {
fallback?: React.ReactNode;
// for the case where the image dimensions are not known before the image is loaded
skeletonWidth?: BoxProps['width'];
skeletonHeight?: BoxProps['height'];
Comment on lines +9 to +11
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since skeletonWidth without skeletonHeight doesn't make much sense (if I understand the comment correctly), it may be better to combine these props into a single object.

Suggested change
// for the case where the image dimensions are not known before the image is loaded
skeletonWidth?: BoxProps['width'];
skeletonHeight?: BoxProps['height'];
// for the case where the image dimensions are not known before the image is loaded
skeletonProps?: BoxProps;

}

export const Image = React.forwardRef<HTMLImageElement, ImageProps>(
function Image(props, ref) {
const { fallback, src, onLoad, onError, ...rest } = props;
const { fallback, src, onLoad, onError, skeletonWidth, skeletonHeight, ...rest } = props;

const [ loading, setLoading ] = React.useState(true);
const [ error, setError ] = React.useState(false);
Expand Down Expand Up @@ -40,9 +43,15 @@ export const Image = React.forwardRef<HTMLImageElement, ImageProps>(
return fallback;
}

const skeletonProps: BoxProps = {
...rest as BoxProps,
...(skeletonWidth !== undefined && { width: skeletonWidth }),
...(skeletonHeight !== undefined && { height: skeletonHeight }),
};

return (
<>
{ loading && <Skeleton loading { ...rest as BoxProps }/> }
{ loading && <Skeleton loading { ...skeletonProps }/> }
<ChakraImage
ref={ ref }
src={ src }
Expand Down
4 changes: 2 additions & 2 deletions ui/marketplace/MarketplaceAppTopBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { Link } from 'toolkit/chakra/link';
import { BackToButton } from 'toolkit/components/buttons/BackToButton';
import { makePrettyLink } from 'toolkit/utils/url';
import RewardsButton from 'ui/rewards/RewardsButton';
import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo';
import NetworkIcon from 'ui/snippets/networkLogo/NetworkIcon';
import UserProfileDesktop from 'ui/snippets/user/profile/UserProfileDesktop';
import UserWalletDesktop from 'ui/snippets/user/wallet/UserWalletDesktop';

Expand Down Expand Up @@ -43,7 +43,7 @@ const MarketplaceAppTopBar = ({ appId, data, isLoading }: Props) => {

return (
<Flex alignItems="center" mb={{ base: 3, md: 2 }} rowGap={ 3 } columnGap={ 2 }>
{ !isMobile && <NetworkLogo isCollapsed mr={ 4 }/> }
{ !isMobile && <NetworkIcon mr={ 4 }/> }
<BackToButton
href={ goBackUrl }
hint="Back to dApps list"
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions ui/snippets/header/Burger.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import IconSvg from 'ui/shared/IconSvg';
import NavigationMobile from 'ui/snippets/navigation/mobile/NavigationMobile';
import RollupStageBadge from 'ui/snippets/navigation/RollupStageBadge';
import TestnetBadge from 'ui/snippets/navigation/TestnetBadge';
import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo';
import NetworkLogo from 'ui/snippets/networkLogo/NetworkLogo';

interface Props {
isMarketplaceAppPage?: boolean;
Expand Down Expand Up @@ -35,8 +35,8 @@ const Burger = ({ isMarketplaceAppPage }: Props) => {
</DrawerTrigger>
<DrawerContent >
<DrawerBody display="flex" flexDirection="column" overflowX="hidden" overflowY="auto">
<TestnetBadge alignSelf="flex-start"/>
<RollupStageBadge alignSelf="flex-start"/>
<TestnetBadge alignSelf="flex-start" mb={ 2 }/>
<RollupStageBadge alignSelf="flex-start" mb={ 2 }/>
<NetworkLogo/>
<NavigationMobile onNavLinkClick={ onClose } isMarketplaceAppPage={ isMarketplaceAppPage }/>
</DrawerBody>
Expand Down
10 changes: 8 additions & 2 deletions ui/snippets/header/HeaderMobile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import React from 'react';
import config from 'configs/app';
import { useIsSticky } from 'toolkit/hooks/useIsSticky';
import RewardsButton from 'ui/rewards/RewardsButton';
import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo';
import NetworkIcon from 'ui/snippets/networkLogo/NetworkIcon';
import UserProfileMobile from 'ui/snippets/user/profile/UserProfileMobile';
import UserWalletMobile from 'ui/snippets/user/wallet/UserWalletMobile';

import RollupStageBadge from '../navigation/RollupStageBadge';
import TestnetBadge from '../navigation/TestnetBadge';
import SearchBarMobile from '../searchBar/SearchBarMobile';
import Burger from './Burger';

Expand Down Expand Up @@ -44,7 +46,11 @@ const HeaderMobile = ({ hideSearchButton, onGoToSearchResults }: Props) => {
boxShadow={ isSticky ? 'md' : 'none' }
>
<Burger/>
<NetworkLogo ml={ 2 } mr="auto"/>
<Flex alignItems="center" flexGrow={ 1 } mx={ 2 }>
<NetworkIcon/>
<TestnetBadge ml={ 2 }/>
<RollupStageBadge ml={ 2 }/>
</Flex>
<Flex columnGap={ 2 }>
{ !hideSearchButton && <SearchBarMobile onGoToSearchResults={ onGoToSearchResults }/> }
{ config.features.rewards.isEnabled && <RewardsButton/> }
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions ui/snippets/navigation/horizontal/NavigationDesktop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import config from 'configs/app';
import useNavItems, { isGroupItem } from 'lib/hooks/useNavItems';
import RewardsButton from 'ui/rewards/RewardsButton';
import { CONTENT_MAX_WIDTH } from 'ui/shared/layout/utils';
import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo';
import NetworkLogo from 'ui/snippets/networkLogo/NetworkLogo';
import UserProfileDesktop from 'ui/snippets/user/profile/UserProfileDesktop';
import UserWalletDesktop from 'ui/snippets/user/wallet/UserWalletDesktop';

Expand All @@ -28,7 +28,7 @@ const NavigationDesktop = () => {
maxW={ `${ CONTENT_MAX_WIDTH }px` }
m="0 auto"
>
<NetworkLogo isCollapsed={ false } w={{ lg: '100%' }} maxW="120px"/>
<NetworkLogo/>
<TestnetBadge ml={ 3 }/>
<RollupStageBadge ml={ 3 }/>
<chakra.nav ml="auto" mr={ config.features.account.isEnabled || config.features.blockchainInteraction.isEnabled ? 8 : 0 }>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 10 additions & 6 deletions ui/snippets/navigation/vertical/NavigationDesktop.pw.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ test.describe('no auth', () => {
});

test('+@dark-mode', async({ page }) => {
await page.locator('a[aria-label="Link to main page"]').hover();
await page.locator('a[aria-label="Link to main page"]').last().hover();
await expect(component).toHaveScreenshot();
});

test.describe('xl screen', () => {
test.use({ viewport: pwConfig.viewport.xl });

test('+@dark-mode', async({ page }) => {
await page.locator('a[aria-label="Link to main page"]').hover();
await page.locator('a[aria-label="Link to main page"]').first().hover();
await expect(component).toHaveScreenshot();
});
});
Expand Down Expand Up @@ -228,7 +228,8 @@ test.describe('with highlighted routes', () => {
);
});

test('+@dark-mode', async() => {
test('+@dark-mode', async({ page }) => {
await page.locator('a[aria-label="Link to main page"]').last().hover();
await expect(component).toHaveScreenshot();
});

Expand All @@ -240,7 +241,8 @@ test.describe('with highlighted routes', () => {
test.describe('xl screen', () => {
test.use({ viewport: pwConfig.viewport.xl });

test('+@dark-mode', async() => {
test('+@dark-mode', async({ page }) => {
await page.locator('a[aria-label="Link to main page"]').first().hover();
await expect(component).toHaveScreenshot();
});
});
Expand Down Expand Up @@ -269,7 +271,8 @@ const promoBannerTest = (type: 'text' | 'image') => {
await component.waitFor({ state: 'visible' });
});

test(`${ darkModeRule }`, async() => {
test(`${ darkModeRule }`, async({ page }) => {
await page.locator('a[aria-label="Link to main page"]').last().hover();
await expect(component).toHaveScreenshot();
});

Expand All @@ -281,7 +284,8 @@ const promoBannerTest = (type: 'text' | 'image') => {
test.describe('xl screen', () => {
test.use({ viewport: pwConfig.viewport.xl });

test(`${ darkModeRule }`, async() => {
test(`${ darkModeRule }`, async({ page }) => {
await page.locator('a[aria-label="Link to main page"]').first().hover();
await expect(component).toHaveScreenshot();
});
});
Expand Down
10 changes: 8 additions & 2 deletions ui/snippets/navigation/vertical/NavigationDesktop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import * as cookies from 'lib/cookies';
import useNavItems, { isGroupItem } from 'lib/hooks/useNavItems';
import IconSvg from 'ui/shared/IconSvg';
import useIsAuth from 'ui/snippets/auth/useIsAuth';
import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo';
import NetworkIcon from 'ui/snippets/networkLogo/NetworkIcon';
import NetworkLogo from 'ui/snippets/networkLogo/NetworkLogo';

import NavigationPromoBanner from '../promoBanner/NavigationPromoBanner';
import RollupStageBadge from '../RollupStageBadge';
Expand Down Expand Up @@ -81,7 +82,12 @@ const NavigationDesktop = () => {
transitionDuration="normal"
transitionTimingFunction="ease"
>
<NetworkLogo isCollapsed={ isCollapsed }/>
<Box display={{ base: 'none', lg: isCollapsed === false ? 'block' : 'none', xl: isCollapsed ? 'none' : 'block' }}>
<NetworkLogo/>
</Box>
<Box display={{ base: 'none', lg: isCollapsed === false ? 'none' : 'block', xl: isCollapsed ? 'block' : 'none' }}>
<NetworkIcon/>
</Box>
</Box>
<Box as="nav" mt={ 6 } w="100%">
<VStack as="ul" gap="1" alignItems="flex-start">
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 59 additions & 0 deletions ui/snippets/networkLogo/NetworkIcon.pw.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import type { Locator } from '@playwright/test';
import React from 'react';

import { test, expect } from 'playwright/lib';

import NetworkIcon from './NetworkIcon';

const ICON_URL = 'https://localhost:3000/my-icon.png';

test.use({ viewport: { width: 30, height: 30 } });

test.describe('placeholder icon', () => {
test.beforeEach(async({ mockEnvs }) => {
await mockEnvs([
[ 'NEXT_PUBLIC_NETWORK_ICON', '' ],
]);
});

test('+@dark-mode', async({ render }) => {
const component = await render(<NetworkIcon/>);

await expect(component).toHaveScreenshot();
});
});

test.describe('custom icon', () => {
let component: Locator;

test.beforeEach(async({ render, mockConfigResponse, mockEnvs }) => {
await mockEnvs([
[ 'NEXT_PUBLIC_NETWORK_ICON', ICON_URL ],
]);
await mockConfigResponse('NEXT_PUBLIC_NETWORK_ICON', ICON_URL, './playwright/mocks/image_svg.svg', true);
component = await render(<NetworkIcon/>);
});

test('+@dark-mode', async() => {
await expect(component).toHaveScreenshot();
});
});

test.describe('custom icon with dark option -@default +@dark-mode', () => {
let component: Locator;

test.beforeEach(async({ render, mockConfigResponse, mockEnvs }) => {
await mockEnvs([
[ 'NEXT_PUBLIC_NETWORK_ICON', ICON_URL ],
[ 'NEXT_PUBLIC_NETWORK_ICON_DARK', ICON_URL ],
]);
await mockConfigResponse('NEXT_PUBLIC_NETWORK_ICON', ICON_URL, './playwright/mocks/image_s.jpg', true);
await mockConfigResponse('NEXT_PUBLIC_NETWORK_ICON_DARK', ICON_URL, './playwright/mocks/image_s.jpg', true);

component = await render(<NetworkIcon/>);
});

test('base view', async() => {
await expect(component).toHaveScreenshot();
});
});
53 changes: 53 additions & 0 deletions ui/snippets/networkLogo/NetworkIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { chakra } from '@chakra-ui/react';
import React from 'react';

import { route } from 'nextjs-routes';

import config from 'configs/app';
import { useColorModeValue } from 'toolkit/chakra/color-mode';
import { Image } from 'toolkit/chakra/image';
import IconSvg from 'ui/shared/IconSvg';

import { INVERT_FILTER } from './consts';

const IconFallback = () => {
return (
<IconSvg
name="networks/icon-placeholder"
w="30px"
h="30px"
color={{ base: 'blue.600', _dark: 'white' }}
aria-label="Network icon placeholder"
/>
);
};

type Props = {
className?: string;
};

const NetworkIcon = ({ className }: Props) => {

const iconSrc = useColorModeValue(config.UI.navigation.icon.default, config.UI.navigation.icon.dark || config.UI.navigation.icon.default);

return (
<chakra.a
className={ className }
href={ route({ pathname: '/' }) }
aria-label="Link to main page"
>
<Image
w="30px"
h="30px"
src={ iconSrc }
alt={ `${ config.chain.name } network icon` }
fallback={ <IconFallback/> }
filter={{ _dark: !config.UI.navigation.icon.dark ? INVERT_FILTER : undefined }}
objectFit="contain"
objectPosition="left"
/>
</chakra.a>
);
};

export default React.memo(chakra(NetworkIcon));
Loading
Loading