Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

378 - Add Skeletons whenever component is loading or data is being fetched via API #392

Closed
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"react-dom": "^18.2.0",
"react-infinite-scroll-component": "^6.1.0",
"react-linkify": "^1.0.0-alpha",
"react-loading-skeleton": "^3.4.0",
"react-redux": "^8.1.0",
"react-router-dom": "^6.13.0",
"react-scripts": "5.0.1",
Expand Down
28 changes: 28 additions & 0 deletions src/components/Post/Skeleton/Styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Skeleton from 'react-loading-skeleton';
import styled from 'styled-components';

export const Div = styled.div`
align-items: center;
border-radius: 5px;
display: flex;
height: 100%;
padding: 0.5rem;
width: 100%;
`;

export const Left = styled.div`
margin-right: 1rem;
`;

export const Right = styled.div`
width: 100%;
`;

export const TextSkeleton = styled(Skeleton)<{$width?: string}>`
margin-bottom: 0.6rem;
width: ${({$width}) => $width};
`;

export const BoxSkeleton = styled(Skeleton)`
min-height: 250px;
`;
38 changes: 38 additions & 0 deletions src/components/Post/Skeleton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import Skeleton from 'react-loading-skeleton';
import * as S from './Styles';
import {SFC} from 'types';

interface PostSkeletonProps {
dataLength: number;
}

const PostSkeleton: SFC<PostSkeletonProps> = ({dataLength}) => {
const renderContent = () => {
return (
<>
<S.Div>
<S.Left>
<Skeleton circle width={50} height={50} />
</S.Left>
<S.Right>
<S.TextSkeleton $width={'20%'} />
</S.Right>
</S.Div>
<S.TextSkeleton />
<S.TextSkeleton $width={'70%'} />
<S.BoxSkeleton />
</>
);
};
return (
<>
{Array(dataLength)
.fill(0)
.map((_, index) => (
<div key={index}>{renderContent()}</div>
))}
</>
);
};

export default PostSkeleton;
11 changes: 8 additions & 3 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ import ReactDOM from 'react-dom/client';
import {Provider} from 'react-redux';
import {PersistGate} from 'redux-persist/integration/react';
import {BrowserRouter} from 'react-router-dom';
import {SkeletonTheme} from 'react-loading-skeleton';

import App from 'containers/App';
import GlobalStyle from 'styles/components/GlobalStyle';
import ToastifyStyle from 'styles/components/ToastifyStyle';
import initSentry from 'config/sentry';
import {persistor, store} from 'store';
import {colors} from 'styles';
import 'react-loading-skeleton/dist/skeleton.css';
import 'styles/fonts.css';

initSentry();
Expand All @@ -19,9 +22,11 @@ root.render(
<PersistGate loading={null} persistor={persistor}>
<GlobalStyle />
<ToastifyStyle />
<BrowserRouter>
<App />
</BrowserRouter>
<SkeletonTheme highlightColor={colors.palette.gray[100]} baseColor={colors.whiteSmoke}>
<BrowserRouter>
<App />
</BrowserRouter>
</SkeletonTheme>
</PersistGate>
</Provider>,
);
25 changes: 25 additions & 0 deletions src/pages/Art/Marketplace/Skeleton/Styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Skeleton from 'react-loading-skeleton';
import styled from 'styled-components';

export const TextSkeleton = styled(Skeleton)<{$width?: string}>`
margin-top: 0.6rem;
width: ${({$width}) => $width};
`;

export const BoxSkeleton = styled(Skeleton)`
border-radius: 14px;
min-height: 292px;
`;

export const Avatar = styled.div`
margin-right: 0.5rem;
`;
export const Text = styled.div`
width: 100%;
`;

export const Div = styled.div`
align-items: center;
display: flex;
width: 100%;
`;
39 changes: 39 additions & 0 deletions src/pages/Art/Marketplace/Skeleton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import Skeleton from 'react-loading-skeleton';
import * as S from './Styles';
import {SFC} from 'types';

interface ArtworkCardSkeletonProps {
dataLength: number;
}

const ArtworkCardSkeleton: SFC<ArtworkCardSkeletonProps> = ({dataLength}) => {
const renderContent = () => {
return (
<>
<S.BoxSkeleton />
<S.TextSkeleton $width={'30%'} />
<S.TextSkeleton />
<S.TextSkeleton $width={'70%'} />
<S.Div>
<S.Avatar>
<Skeleton circle width={25} height={25} />
</S.Avatar>
<S.Text>
<S.TextSkeleton width={'50%'} />
</S.Text>
</S.Div>
</>
);
};
return (
<>
{Array(dataLength)
.fill(0)
.map((_, index) => (
<div key={index}>{renderContent()}</div>
))}
</>
);
};

export default ArtworkCardSkeleton;
36 changes: 17 additions & 19 deletions src/pages/Art/Marketplace/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import {useDispatch, useSelector} from 'react-redux';
import ArtworkCard from 'components/ArtworkCard';
import EmptyText from 'components/EmptyText';
import InfiniteScroll from 'components/InfiniteScroll';
import ArtworkCardSkeleton from './Skeleton';
import {AppDispatch, SFC} from 'types';
import {getArtworks as _getArtworks, resetArtworks as _resetArtworks} from 'dispatchers/artworks';
import {getArtworks as getArtworksState} from 'selectors/state';

import * as S from './Styles';

const Marketplace: SFC = ({className}) => {
Expand Down Expand Up @@ -35,28 +35,26 @@ const Marketplace: SFC = ({className}) => {
};

const renderArtworkCards = () => {
if (artworkList.length) {
return (
<S.ArtworkCards>
{artworkList.map((artwork) => (
<ArtworkCard artwork={artwork} key={artwork.id} />
))}
</S.ArtworkCards>
);
}
return (
<S.ArtworkCards>
{isLoading && <ArtworkCardSkeleton dataLength={20} />}
{artworkList.map((artwork) => (
<ArtworkCard artwork={artwork} key={artwork.id} />
))}
</S.ArtworkCards>
);
};

const renderContent = () => {
if (!!artworkList.length) {
return (
<>
<S.ArtworkCardsHeading>Buy from our marketplace</S.ArtworkCardsHeading>
{renderArtworkCards()}
</>
);
if (!isLoading && !artworkList.length) {
return <EmptyText>No artwork to display.</EmptyText>;
}

return <EmptyText>No artwork to display.</EmptyText>;
return (
<>
<S.ArtworkCardsHeading>Buy from our marketplace</S.ArtworkCardsHeading>
{renderArtworkCards()}
</>
);
};

return (
Expand Down
53 changes: 53 additions & 0 deletions src/pages/Contributions/Skeleton/Styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import Skeleton from 'react-loading-skeleton';
import styled from 'styled-components';
import {colors} from 'styles';
import {Col} from 'styles/components/GridStyle';

export const Avatar = styled.div`
margin-right: 1rem;
`;

export const Text = styled.div`
width: 100%;
`;

export const TextSkeleton = styled(Skeleton)<{$float?: string; $marginLeft?: string; $width?: string}>`
float: ${({$float}) => $float};
margin-left: ${({$marginLeft}) => $marginLeft};
margin-top: 0.6rem;
width: ${({$width}) => $width};
`;

export const Box = styled.div<{$padding?: string}>`
align-items: center;
display: flex;
justify-content: space-between;
margin-bottom: 8px;
padding: ${({$padding}) => $padding};
width: 100%;
`;
export const BoxLeft = styled.div`
align-items: center;
display: flex;
width: 100%;
`;
export const BoxRight = styled.div`
width: 100%;
`;

export const Column = styled(Col)`
border-radius: 14px;
border: 1px solid ${colors.border};
padding: 10px;
`;

export const Card = styled.div`
display: flex;
flex-direction: column;
justify-content: space-between;
min-height: 276px;
`;

export const Div = styled.div`
margin-top: 10px;
`;
88 changes: 88 additions & 0 deletions src/pages/Contributions/Skeleton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import Skeleton from 'react-loading-skeleton';
import Line from 'components/Line';
import {SFC} from 'types';
import * as S from './Styles';

interface ContributionsSkeletonProps {
dataLength: number;
}

const ContributionsSkeleton: SFC<ContributionsSkeletonProps> = ({dataLength}) => {
const cardHeader = () => {
return (
<>
<S.Box>
<S.BoxLeft>
<S.Avatar>
<Skeleton circle width={50} height={50} />
</S.Avatar>
<S.Text>
<S.TextSkeleton width={'40%'} />
</S.Text>
</S.BoxLeft>
<S.BoxRight>
<S.TextSkeleton width={'40%'} $float={'inline-end'} />
</S.BoxRight>
</S.Box>
<Line />
</>
);
};
const renderContent = () => {
return (
<>
<S.Avatar>
<Skeleton circle width={25} height={25} />
</S.Avatar>
<S.Text>
<S.TextSkeleton width={'50%'} />
</S.Text>
</>
);
};
const cardBody = () => {
return (
<S.Box $padding={'10px'}>
{renderContent()}
{renderContent()}
</S.Box>
);
};
const cardFooter = () => {
return (
<>
<S.Box>
<S.Avatar>
<Skeleton circle width={50} height={50} />
</S.Avatar>
<S.Text>
<S.TextSkeleton width={'30%'} />
</S.Text>
</S.Box>
<S.TextSkeleton width={'80%'} count={2} $marginLeft={'60px'} />
</>
);
};
return (
<>
{Array(dataLength)
.fill(0)
.map((_, index) => (
<S.Column size={6} key={index}>
<S.Card>
<div>
{cardHeader()}
{cardBody()}
{cardBody()}
</div>
<Line />

<S.Div>{cardFooter()}</S.Div>
</S.Card>
</S.Column>
))}
</>
);
};

export default ContributionsSkeleton;
Loading