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

[#10] [UI] As a user, I can see the shimmer loading on Dashboard page #53

Merged
merged 3 commits into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
16 changes: 16 additions & 0 deletions src/components/Dashboard/Content/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';

import { render, screen } from '@testing-library/react';

import DashboardContent from '.';

describe('DashboardContent', () => {
const dataTestId = 'dashboard-content';
it('renders DashboardContent and its components', () => {
render(<DashboardContent data-test-id={dataTestId} />);
manh-t marked this conversation as resolved.
Show resolved Hide resolved

const dashboardContent = screen.getByTestId(dataTestId);

expect(dashboardContent).toBeVisible();
});
});
24 changes: 24 additions & 0 deletions src/components/Dashboard/Content/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react';

import Shimmer from 'components/Shimmer';

interface DashboardContentProps {
'data-test-id'?: string;
}

const DashboardContent = ({ ...attributes }: DashboardContentProps): JSX.Element => {
return (
<div className="flex flex-col w-full" {...attributes}>
manh-t marked this conversation as resolved.
Show resolved Hide resolved
<Shimmer classAttributes="h-[302px] rounded-[12px]" />
<div className="flex flex-row justify-between mt-[38px]">
<div className="flex flex-col justify-between">
<Shimmer classAttributes="w-[318px] h-[18px] rounded-[14px]" />
<Shimmer classAttributes="w-[212px] h-[18px] rounded-[14px]" />
</div>
<Shimmer classAttributes="w-[56px] h-[56px] rounded-full" />
</div>
</div>
);
};

export default DashboardContent;
30 changes: 26 additions & 4 deletions src/components/Dashboard/Header/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@ import DashboardHeader from '.';

describe('DashboardHeader', () => {
const dataTestId = 'dashboard-header';
it('renders DashboardHeader and its components', () => {
it('renders DashboardHeader and its components without shimmers', () => {
const dateTime = 'Monday, JUNE 15';
const daysAgo = 'Today';
const profileUrl = 'test url';
render(
<DashboardHeader dateTime={dateTime} daysAgo={daysAgo} profileUrl={profileUrl} data-test-id={dataTestId}>
<DashboardHeader
dateTime={dateTime}
daysAgo={daysAgo}
profileUrl={profileUrl}
data-test-id={dataTestId}
shouldShowShimmer={false}
>
Dashboard Header
</DashboardHeader>
);
Expand All @@ -21,10 +27,26 @@ describe('DashboardHeader', () => {

expect(dashboardHeader).toBeVisible();
expect(dashboardHeader).toHaveTextContent(dateTime);
expect(dashboardHeader).toHaveTextContent(dateTime);
expect(dashboardHeader).toHaveTextContent(dateTime);
expect(dashboardHeader).toHaveTextContent(daysAgo);

expect(avatar).toBeVisible();
expect(avatar).toHaveAttribute('src', profileUrl);
});

it('does NOT renders text components', () => {
const dateTime = 'Monday, JUNE 15';
const daysAgo = 'Today';
const profileUrl = 'test url';
render(
<DashboardHeader dateTime={dateTime} daysAgo={daysAgo} profileUrl={profileUrl} data-test-id={dataTestId}>
Dashboard Header
</DashboardHeader>
);

const dashboardHeader = screen.getByTestId(dataTestId);

expect(dashboardHeader).toBeVisible();
expect(dashboardHeader).not.toHaveTextContent(dateTime);
expect(dashboardHeader).not.toHaveTextContent(daysAgo);
});
});
35 changes: 29 additions & 6 deletions src/components/Dashboard/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,53 @@
import React from 'react';

import { ReactComponent as NimbleLogoWhite } from 'assets/images/icons/nimble-logo-white.svg';
import Shimmer from 'components/Shimmer';

interface DashboardHeaderProps {
dateTime: string;
daysAgo: string;
profileUrl: string;
shouldShowShimmer?: boolean;
children: React.ReactNode;
'data-test-id'?: string;
}
const DashboardHeader = ({ dateTime, daysAgo, profileUrl, children, ...rest }: DashboardHeaderProps): JSX.Element => {
const DashboardHeader = ({
dateTime,
daysAgo,
profileUrl,
shouldShowShimmer = true,
children,
...rest
}: DashboardHeaderProps): JSX.Element => {
return (
<header className="flex flex-col min-h-screen" {...rest}>
<div className="flex justify-between pt-8">
<NimbleLogoWhite />
<img className="w-[36px] h-[36px] rounded-full" src={profileUrl} alt="user avatar" />
{shouldShowShimmer ? <Shimmer classAttributes="w-[117px] h-[18px] rounded-[14px]" /> : <NimbleLogoWhite />}
manh-t marked this conversation as resolved.
Show resolved Hide resolved
{shouldShowShimmer ? (
<Shimmer classAttributes="w-[36px] h-[36px] rounded-full" />
) : (
<img className="w-[36px] h-[36px] rounded-full" src={profileUrl} alt="user avatar" />
)}
</div>
<div className="flex justify-between">
<div className="w-1/5"></div>
<div className="flex flex-col text-white mt-10 flex-1">
<p className="text-x-small font-extrabold">{dateTime}</p>
<p className="text-x-large font-extrabold mt-1">{daysAgo}</p>
{shouldShowShimmer ? (
<Shimmer classAttributes="w-[117px] h-[18px] rounded-[14px]" />
) : (
<p className="text-x-small font-extrabold">{dateTime}</p>
)}
{shouldShowShimmer ? (
<div className="mt-[14px]">
<Shimmer classAttributes="w-[100px] h-[18px] rounded-[14px]" />
</div>
) : (
<p className="text-x-large font-extrabold mt-1">{daysAgo}</p>
)}
</div>
<div className="w-1/5"></div>
</div>
<div className="flex justify-between mt-8 grow">
<div className="flex justify-between mt-8">
<div className="w-1/5"></div>
<div className="flex-1">{children}</div>
<div className="w-1/5"></div>
Expand Down
18 changes: 18 additions & 0 deletions src/components/Shimmer/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';

import { render, screen } from '@testing-library/react';

import Shimmer from '.';

describe('Shimmer', () => {
const dataTestId = 'shimmer';
it('renders Shimmer and its components', () => {
const testClass = 'test-class';
render(<Shimmer classAttributes={testClass} data-test-id={dataTestId} />);
manh-t marked this conversation as resolved.
Show resolved Hide resolved

const shimmer = screen.getByTestId(dataTestId);

expect(shimmer).toBeVisible();
expect(shimmer).toHaveClass(testClass);
});
});
20 changes: 20 additions & 0 deletions src/components/Shimmer/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';

interface ShimmerProps {
classAttributes: string;
'data-test-id'?: string;
}

// Ref: https://delba.dev/blog/animated-loading-skeletons-with-tailwind
const Shimmer = ({ classAttributes, ...attributes }: ShimmerProps): JSX.Element => {
manh-t marked this conversation as resolved.
Show resolved Hide resolved
return (
<div
className={`relative before:absolute before:inset-0 before:-translate-x-full before:animate-[shimmer_2s_infinite] before:bg-gradient-to-r before:from-transparent before:from-30% before:via-white/50 before:to-transparent before:to-70% isolate overflow-hidden shadow-xl shadow-black/5 ${classAttributes}`}
manh-t marked this conversation as resolved.
Show resolved Hide resolved
{...attributes}
>
<div className={`bg-white bg-opacity-[.12] ${classAttributes}`}></div>
</div>
);
};

export default Shimmer;
4 changes: 2 additions & 2 deletions src/screens/Dashboard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React from 'react';

import DashboardEmpty from 'components/Dashboard/Empty';
import DashboardContent from 'components/Dashboard/Content';
import DashboardHeader from 'components/Dashboard/Header';

const DashBoardScreen = (): JSX.Element => {
return (
<div className="bg-black w-full h-full pl-8 pr-8">
<DashboardHeader dateTime="Monday, JUNE 15" daysAgo="Today" profileUrl="https://i.pravatar.cc/150?img=3">
<div className="w-full flex justify-center mt-36">
<DashboardEmpty />
<DashboardContent />
</div>
</DashboardHeader>
</div>
Expand Down
7 changes: 7 additions & 0 deletions tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ module.exports = {
'survey-wide': '-0.08px',
'survey-wider': '0.38px',
},
keyframes: {
shimmer: {
'100%': {
transform: 'translateX(100%)',
},
},
},
},
},
plugins: [],
Expand Down