diff --git a/src/components/Dashboard/Content/index.test.tsx b/src/components/Dashboard/Content/index.test.tsx new file mode 100644 index 0000000..5a81ccb --- /dev/null +++ b/src/components/Dashboard/Content/index.test.tsx @@ -0,0 +1,15 @@ +import React from 'react'; + +import { render, screen } from '@testing-library/react'; + +import DashboardContent, { dashboardDataTestIds } from '.'; + +describe('DashboardContent', () => { + it('renders DashboardContent and its components', () => { + render(); + + 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 new file mode 100644 index 0000000..4063583 --- /dev/null +++ b/src/components/Dashboard/Content/index.tsx @@ -0,0 +1,24 @@ +import React from 'react'; + +import Shimmer from 'components/Shimmer'; + +export const dashboardDataTestIds = { + content: 'dashboard__content', +}; + +const DashboardContent = (): JSX.Element => { + return ( +
+ +
+
+ + +
+ +
+
+ ); +}; + +export default DashboardContent; 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/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.test.tsx b/src/components/Shimmer/index.test.tsx new file mode 100644 index 0000000..2290e4a --- /dev/null +++ b/src/components/Shimmer/index.test.tsx @@ -0,0 +1,17 @@ +import React from 'react'; + +import { render, screen } from '@testing-library/react'; + +import Shimmer, { shimmerDataTestIds } from '.'; + +describe('Shimmer', () => { + it('renders Shimmer and its components', () => { + const testClass = 'test-class'; + render(); + + 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 new file mode 100644 index 0000000..0462435 --- /dev/null +++ b/src/components/Shimmer/index.tsx @@ -0,0 +1,24 @@ +import React from 'react'; + +import classNames from 'classnames'; + +interface ShimmerProps { + classAttributes: string; +} + +export const shimmerDataTestIds = { + content: 'shimmer__content', +}; + +// Ref: https://delba.dev/blog/animated-loading-skeletons-with-tailwind +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 ( +
+
+
+ ); +}; + +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: [],