Skip to content

Commit 2e1b9a1

Browse files
committed
Get rid of layout shift on item page
1 parent 3b1bb24 commit 2e1b9a1

File tree

16 files changed

+42
-93
lines changed

16 files changed

+42
-93
lines changed

packages/frontend/components/header/component.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export const Header = () => {
8080
<header css={styles.header}>
8181
<Container cssExtend={styles.headerInner}>
8282
<Flex align="center">
83-
<Link href={Routes.DEFAULT}>
83+
<Link prefetch={false} href={Routes.DEFAULT}>
8484
<a>
8585
<Logo />
8686
</a>

packages/frontend/components/item/component.tsx

+5-12
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,11 @@
22
import type { ItemDto } from '@vse-bude/shared';
33
import { ProductType } from '@vse-bude/shared';
44
import { Container } from '@primitives';
5-
import { lightTheme } from 'theme';
65
import {
76
deleteProductFromFavorites,
87
addProductToFavorites,
98
} from 'store/favorite-product';
10-
import {
11-
useAppDispatch,
12-
useWindowSize,
13-
useInFavorite,
14-
useTypedSelector,
15-
} from '@hooks';
9+
import { useAppDispatch, useInFavorite, useTypedSelector } from '@hooks';
1610
import { fetchCreateOrder } from 'store/checkout';
1711
import { useRouter } from 'next/router';
1812
import { Routes } from '@enums';
@@ -27,8 +21,6 @@ interface ItemProps {
2721
}
2822

2923
export const Item = ({ item }: ItemProps) => {
30-
const windowSize = useWindowSize();
31-
3224
const dispatch = useAppDispatch();
3325

3426
const router = useRouter();
@@ -57,11 +49,12 @@ export const Item = ({ item }: ItemProps) => {
5749
return (
5850
<React.Fragment>
5951
<Container cssExtend={styles.itemWrapper}>
60-
{windowSize.width > lightTheme.breakpoints.sm ? (
52+
<div className="desktop-gallery-wrapper">
6153
<ItemImageSlider imageLinks={item.imageLinks} />
62-
) : (
54+
</div>
55+
<div className="mobile-gallery-wrapper">
6356
<ImageSliderSplide imageLinks={item.imageLinks} />
64-
)}
57+
</div>
6558
{item.type === ProductType.SELLING ? (
6659
<ItemInfoSelling
6760
item={item}

packages/frontend/components/item/image-slider-splide/component.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const ImageSliderSplide = ({ imageLinks }: ImageSliderSplideProps) => (
2323
key={link + index}
2424
layout="fill"
2525
objectFit="cover"
26+
priority={index < 4}
2627
/>
2728
<span css={styles.numberSlide}>
2829
<span css={styles.current}>{index + 1}</span>/

packages/frontend/components/item/image-slider/component.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export const ItemImageSlider = ({ imageLinks }: ItemImageSliderProps) => {
2525
key={index}
2626
onClick={() => handleClick(index)}
2727
src={link}
28+
priority={index < 4}
2829
alt="item image"
2930
layout="fill"
3031
objectFit="cover"

packages/frontend/components/item/item-info-auction/component.tsx

+3-7
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
} from 'store/product';
1818
import { UPDATE_PRODUCT_PRICE } from '@vse-bude/shared';
1919
import { getAuctionItemIo } from '@helpers';
20-
import Link from 'next/link';
20+
import { useRouter } from 'next/router';
2121
import { CountDownTimer } from '../countdown-timer/component';
2222
import { ItemTitle, ItemInfo, ItemPrice } from '../item-info';
2323
import { minBidValidation } from '../validation';
@@ -40,7 +40,7 @@ export const ItemInfoAuction = ({
4040
onChangeIsFavorite,
4141
}: ItemInfoAuctionProps) => {
4242
const [confirmModalVisible, setModalVisible] = useState(false);
43-
43+
const { push } = useRouter();
4444
const { t } = useTranslation('item');
4545
const { user } = useTypedSelector((state) => state.auth);
4646

@@ -114,11 +114,7 @@ export const ItemInfoAuction = ({
114114
};
115115

116116
const renderEditButton = () => (
117-
<Link href={`/items/edit/${item.id}`}>
118-
<a style={{ textDecoration: 'none' }}>
119-
<Button>Edit</Button>
120-
</a>
121-
</Link>
117+
<Button onClick={() => push(`/items/edit/${item.id}`)}>Edit</Button>
122118
);
123119

124120
const renderBidButtons = () => (

packages/frontend/components/item/item-info/seller-info/component.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export const SellerInfo = ({ seller, onContactSeller }: SellerInfoProps) => {
3737
image={seller.avatar}
3838
handleClick={handleAvatarClick}
3939
/>
40-
<Link href={`${Routes.PROFILE}/${seller.id}`} passHref>
40+
<Link prefetch={false} href={`${Routes.PROFILE}/${seller.id}`} passHref>
4141
<span>{seller.firstName + ' ' + seller.lastName}</span>
4242
</Link>
4343
</div>

packages/frontend/components/item/styles.ts

+18
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,27 @@ import { css } from '@emotion/react';
44
export const itemWrapper = ({ spaces, breakpoints }: Theme) => css`
55
display: flex;
66
margin-bottom: ${spaces.xl11};
7+
8+
.desktop-gallery-wrapper,
9+
.mobile-gallery-wrapper {
10+
display: contents;
11+
}
12+
713
@media (max-width: ${breakpoints.xl}px) {
814
flex-direction: column;
915
justify-content: center;
1016
align-items: center;
1117
}
18+
19+
@media (max-width: ${breakpoints.sm}px) {
20+
.desktop-gallery-wrapper {
21+
display: none;
22+
}
23+
}
24+
25+
@media (min-width: ${breakpoints.sm + 1}px) {
26+
.mobile-gallery-wrapper {
27+
display: none;
28+
}
29+
}
1230
`;

packages/frontend/components/primitives/modal/component.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useEffect } from 'react';
2-
import ReactDOM from 'react-dom';
2+
import { createPortal } from 'react-dom';
33
import * as styles from './styles';
44
import type { ModalProps } from './types';
55

@@ -23,7 +23,7 @@ export const Modal = ({ visible, children }: ModalProps) => {
2323
);
2424

2525
const renderPortal = () =>
26-
ReactDOM.createPortal(renderPortalBody(), document.querySelector('#modal'));
26+
createPortal(renderPortalBody(), document.querySelector('#modal'));
2727

2828
return <React.Fragment>{visible && renderPortal()}</React.Fragment>;
2929
};

packages/frontend/components/primitives/popover/component.tsx

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useCallback, useEffect, useRef, useState } from 'react';
2-
import ReactDOM from 'react-dom';
2+
import { createPortal } from 'react-dom';
33
import { resetButton } from 'theme';
44
import { useOutsideClick } from '@hooks';
55
import type { PopoverProps } from './types';
@@ -92,10 +92,7 @@ export const Popover = ({
9292
);
9393

9494
const renderPortal = () =>
95-
ReactDOM.createPortal(
96-
renderPortalBody(),
97-
document.querySelector('#popover'),
98-
);
95+
createPortal(renderPortalBody(), document.querySelector('#popover'));
9996

10097
return (
10198
<React.Fragment>

packages/frontend/components/primitives/tooltip/component.tsx

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Fragment, useRef, useEffect, useState, useCallback } from 'react';
2-
import * as ReactDOM from 'react-dom';
2+
import { createPortal } from 'react-dom';
33
import * as styles from './styles';
44
import type { TooltipProps } from './types';
55

@@ -103,10 +103,7 @@ export const Tooltip = ({
103103
);
104104

105105
const renderPortal = () =>
106-
ReactDOM.createPortal(
107-
renderPortalBody(),
108-
document.querySelector('#portal'),
109-
);
106+
createPortal(renderPortalBody(), document.querySelector('#portal'));
110107

111108
return (
112109
<Fragment>

packages/frontend/pages/_document.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ class CustomDocument extends Document {
4444
</Head>
4545
<body>
4646
<Main />
47+
<div id="portal" />
48+
<div id="popover" />
49+
<div id="modal" />
4750
<NextScript />
48-
<div id="portal"></div>
49-
<div id="popover"></div>
50-
<div id="modal"></div>
5151
</body>
5252
</Html>
5353
);

packages/frontend/providers/ThemeProvider/index.tsx

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ReactNode } from 'react';
2-
import { useState, useInsertionEffect } from 'react';
2+
import { useState } from 'react';
33
import { Global, ThemeProvider as ThemeProviderEmotion } from '@emotion/react';
44
import { darkTheme, lightTheme, globalStyles } from 'theme';
55

@@ -15,10 +15,6 @@ const colorSchemes = {
1515
const ThemeProvider = ({ children }: ThemeProviderProps) => {
1616
const [theme] = useState(colorSchemes['light']);
1717

18-
useInsertionEffect(() => {
19-
document.body.style.opacity = '1';
20-
}, []);
21-
2218
return (
2319
<ThemeProviderEmotion theme={theme}>
2420
<Global styles={globalStyles} />

packages/frontend/public/images/favicon/site.webmanifest

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
"scope": "/",
66
"icons": [
77
{
8-
"src": "images/favicon/android-chrome-192x192.png",
8+
"src": "/android-chrome-192x192.png",
99
"sizes": "192x192",
1010
"type": "image/png"
1111
},
1212
{
13-
"src": "/images/favicon/android-chrome-512x512.png",
13+
"src": "/android-chrome-512x512.png",
1414
"sizes": "512x512",
1515
"type": "image/png"
1616
}
-527 KB
Binary file not shown.

packages/frontend/public/images/noavatar.svg

-46
This file was deleted.

packages/frontend/theme/globalStyles.tsx

-4
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@ export const globalStyles = (theme: Theme) => css`
2121
min-height: 100vh;
2222
}
2323
24-
body {
25-
opacity: 0;
26-
}
27-
2824
body,
2925
ul,
3026
li {

0 commit comments

Comments
 (0)