From 2845300c8f89afb0a4cbcc5ed4828b68967a3bde Mon Sep 17 00:00:00 2001 From: Tran Manh Date: Wed, 21 Jun 2023 16:03:21 +0700 Subject: [PATCH 1/3] [#10] Create Shimmer loading --- src/components/Dashboard/Content/index.tsx | 20 +++++++++++++ src/components/Dashboard/Header/index.tsx | 35 ++++++++++++++++++---- src/components/Shimmer/index.tsx | 18 +++++++++++ src/screens/Dashboard/index.tsx | 4 +-- tailwind.config.js | 7 +++++ 5 files changed, 76 insertions(+), 8 deletions(-) create mode 100644 src/components/Dashboard/Content/index.tsx create mode 100644 src/components/Shimmer/index.tsx diff --git a/src/components/Dashboard/Content/index.tsx b/src/components/Dashboard/Content/index.tsx new file mode 100644 index 0000000..e929ee4 --- /dev/null +++ b/src/components/Dashboard/Content/index.tsx @@ -0,0 +1,20 @@ +import React from 'react'; + +import Shimmer from 'components/Shimmer'; + +const DashboardContent = (): JSX.Element => { + return ( +
+ +
+
+ + +
+ +
+
+ ); +}; + +export default DashboardContent; diff --git a/src/components/Dashboard/Header/index.tsx b/src/components/Dashboard/Header/index.tsx index 74c9b12..af06730 100644 --- a/src/components/Dashboard/Header/index.tsx +++ b/src/components/Dashboard/Header/index.tsx @@ -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 (
- - user avatar + {shouldShowShimmer ? : } + {shouldShowShimmer ? ( + + ) : ( + user avatar + )}
-

{dateTime}

-

{daysAgo}

+ {shouldShowShimmer ? ( + + ) : ( +

{dateTime}

+ )} + {shouldShowShimmer ? ( +
+ +
+ ) : ( +

{daysAgo}

+ )}
-
+
{children}
diff --git a/src/components/Shimmer/index.tsx b/src/components/Shimmer/index.tsx new file mode 100644 index 0000000..e3ad5ce --- /dev/null +++ b/src/components/Shimmer/index.tsx @@ -0,0 +1,18 @@ +import React from 'react'; + +interface ShimmerProps { + classAttributes: string; +} + +// Ref: https://delba.dev/blog/animated-loading-skeletons-with-tailwind +const Shimmer = ({ classAttributes }: ShimmerProps): JSX.Element => { + return ( +
+
+
+ ); +}; + +export default Shimmer; diff --git a/src/screens/Dashboard/index.tsx b/src/screens/Dashboard/index.tsx index b02a0a2..de85c38 100644 --- a/src/screens/Dashboard/index.tsx +++ b/src/screens/Dashboard/index.tsx @@ -1,6 +1,6 @@ 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 => { @@ -8,7 +8,7 @@ const DashBoardScreen = (): JSX.Element => {
- +
diff --git a/tailwind.config.js b/tailwind.config.js index 5170301..53183bd 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -28,6 +28,13 @@ module.exports = { 'survey-wide': '-0.08px', 'survey-wider': '0.38px', }, + keyframes: { + shimmer: { + '100%': { + transform: 'translateX(100%)', + }, + }, + }, }, }, plugins: [], From 10cfe6715223c3f3e1d64e775d4f76cb3acfa2ae Mon Sep 17 00:00:00 2001 From: Tran Manh Date: Tue, 27 Jun 2023 17:27:13 +0700 Subject: [PATCH 2/3] [#10] Update unittest for components --- .../Dashboard/Content/index.test.tsx | 16 ++++++++++ src/components/Dashboard/Content/index.tsx | 8 +++-- .../Dashboard/Header/index.test.tsx | 30 ++++++++++++++++--- src/components/Shimmer/index.test.tsx | 18 +++++++++++ src/components/Shimmer/index.tsx | 4 ++- 5 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 src/components/Dashboard/Content/index.test.tsx create mode 100644 src/components/Shimmer/index.test.tsx diff --git a/src/components/Dashboard/Content/index.test.tsx b/src/components/Dashboard/Content/index.test.tsx new file mode 100644 index 0000000..a33e771 --- /dev/null +++ b/src/components/Dashboard/Content/index.test.tsx @@ -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(); + + const dashboardContent = screen.getByTestId(dataTestId); + + expect(dashboardContent).toBeVisible(); + }); +}); diff --git a/src/components/Dashboard/Content/index.tsx b/src/components/Dashboard/Content/index.tsx index e929ee4..97f91c3 100644 --- a/src/components/Dashboard/Content/index.tsx +++ b/src/components/Dashboard/Content/index.tsx @@ -2,9 +2,13 @@ import React from 'react'; import Shimmer from 'components/Shimmer'; -const DashboardContent = (): JSX.Element => { +interface DashboardContentProps { + 'data-test-id'?: string; +} + +const DashboardContent = ({ ...attributes }: DashboardContentProps): JSX.Element => { return ( -
+
diff --git a/src/components/Dashboard/Header/index.test.tsx b/src/components/Dashboard/Header/index.test.tsx index ee05ac2..b1b7fce 100644 --- a/src/components/Dashboard/Header/index.test.tsx +++ b/src/components/Dashboard/Header/index.test.tsx @@ -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( - + Dashboard Header ); @@ -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( + + Dashboard Header + + ); + + const dashboardHeader = screen.getByTestId(dataTestId); + + expect(dashboardHeader).toBeVisible(); + expect(dashboardHeader).not.toHaveTextContent(dateTime); + expect(dashboardHeader).not.toHaveTextContent(daysAgo); + }); }); diff --git a/src/components/Shimmer/index.test.tsx b/src/components/Shimmer/index.test.tsx new file mode 100644 index 0000000..ae4dc70 --- /dev/null +++ b/src/components/Shimmer/index.test.tsx @@ -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(); + + const shimmer = screen.getByTestId(dataTestId); + + expect(shimmer).toBeVisible(); + expect(shimmer).toHaveClass(testClass); + }); +}); diff --git a/src/components/Shimmer/index.tsx b/src/components/Shimmer/index.tsx index e3ad5ce..7dbe178 100644 --- a/src/components/Shimmer/index.tsx +++ b/src/components/Shimmer/index.tsx @@ -2,13 +2,15 @@ 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 }: ShimmerProps): JSX.Element => { +const Shimmer = ({ classAttributes, ...attributes }: ShimmerProps): JSX.Element => { return (
From 12170845565d5a49fae18d0a559885cc87f25cc6 Mon Sep 17 00:00:00 2001 From: Tran Manh Date: Mon, 24 Jul 2023 11:09:21 +0700 Subject: [PATCH 3/3] [#10] Fix issues by comments --- .../Dashboard/Content/index.test.tsx | 7 +++---- src/components/Dashboard/Content/index.tsx | 10 +++++----- src/components/Shimmer/index.test.tsx | 7 +++---- src/components/Shimmer/index.tsx | 18 +++++++++++------- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/components/Dashboard/Content/index.test.tsx b/src/components/Dashboard/Content/index.test.tsx index a33e771..5a81ccb 100644 --- a/src/components/Dashboard/Content/index.test.tsx +++ b/src/components/Dashboard/Content/index.test.tsx @@ -2,14 +2,13 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; -import DashboardContent from '.'; +import DashboardContent, { dashboardDataTestIds } from '.'; describe('DashboardContent', () => { - const dataTestId = 'dashboard-content'; it('renders DashboardContent and its components', () => { - render(); + render(); - const dashboardContent = screen.getByTestId(dataTestId); + const dashboardContent = screen.getByTestId(dashboardDataTestIds.content); expect(dashboardContent).toBeVisible(); }); diff --git a/src/components/Dashboard/Content/index.tsx b/src/components/Dashboard/Content/index.tsx index 97f91c3..4063583 100644 --- a/src/components/Dashboard/Content/index.tsx +++ b/src/components/Dashboard/Content/index.tsx @@ -2,13 +2,13 @@ import React from 'react'; import Shimmer from 'components/Shimmer'; -interface DashboardContentProps { - 'data-test-id'?: string; -} +export const dashboardDataTestIds = { + content: 'dashboard__content', +}; -const DashboardContent = ({ ...attributes }: DashboardContentProps): JSX.Element => { +const DashboardContent = (): JSX.Element => { return ( -
+
diff --git a/src/components/Shimmer/index.test.tsx b/src/components/Shimmer/index.test.tsx index ae4dc70..2290e4a 100644 --- a/src/components/Shimmer/index.test.tsx +++ b/src/components/Shimmer/index.test.tsx @@ -2,15 +2,14 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; -import Shimmer from '.'; +import Shimmer, { shimmerDataTestIds } from '.'; describe('Shimmer', () => { - const dataTestId = 'shimmer'; it('renders Shimmer and its components', () => { const testClass = 'test-class'; - render(); + render(); - const shimmer = screen.getByTestId(dataTestId); + const shimmer = screen.getByTestId(shimmerDataTestIds.content); expect(shimmer).toBeVisible(); expect(shimmer).toHaveClass(testClass); diff --git a/src/components/Shimmer/index.tsx b/src/components/Shimmer/index.tsx index 7dbe178..0462435 100644 --- a/src/components/Shimmer/index.tsx +++ b/src/components/Shimmer/index.tsx @@ -1,18 +1,22 @@ import React from 'react'; +import classNames from 'classnames'; + interface ShimmerProps { classAttributes: string; - 'data-test-id'?: string; } +export const shimmerDataTestIds = { + content: 'shimmer__content', +}; + // Ref: https://delba.dev/blog/animated-loading-skeletons-with-tailwind -const Shimmer = ({ classAttributes, ...attributes }: ShimmerProps): JSX.Element => { +const Shimmer = ({ classAttributes }: ShimmerProps): JSX.Element => { + const DEFAULT_CLASSNAME_ATTRIBUTES = + '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'; return ( -
-
+
+
); };