From e2d3cafff89b77eb66e7bc19e3bf0f3c544c3d53 Mon Sep 17 00:00:00 2001 From: Rushi Vishavadia Date: Sat, 6 Aug 2022 18:53:33 +0530 Subject: [PATCH 1/8] Refactor Skeleton to use TW classes, has better animation and ability to easily create Skeletons quickly --- src/components/Skeleton.jsx | 58 ++++++++++++++++----- src/index.js | 2 +- src/stories/DataDisplay/Skeleton.stories.js | 35 ++++++++++--- tailwind.config.js | 8 +++ 4 files changed, 82 insertions(+), 21 deletions(-) diff --git a/src/components/Skeleton.jsx b/src/components/Skeleton.jsx index 1059921a..0b56ccc2 100644 --- a/src/components/Skeleton.jsx +++ b/src/components/Skeleton.jsx @@ -1,31 +1,61 @@ import clsx from "clsx"; import PropTypes from "prop-types"; import React from "react"; -import styles from "./Skeleton.module.css"; +import { range, uniqueId } from "lodash"; -export const Skeleton = ({ style, height = 300, shouldAnimate = true, children, classNames = {}, ...rest }) => { +export const Skeleton = ({ height = "h-full", children, className, ...rest }) => { return (
- {shouldAnimate ? ( -
- ) : null} -
{children}
+ {children ?? "Loading..."}
); }; Skeleton.propTypes = { - style: PropTypes.object, - height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - shouldAnimate: PropTypes.bool, - classNames: PropTypes.object, + height: PropTypes.string, + className: PropTypes.string, children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]), }; + +export const SkeletonList = ({ grid = [3, 2], classNames = {} }) => { + const [horizontalCount, verticalCount] = grid; + const horizontalClasses = `grid grid-cols-${horizontalCount} gap-x-2`; + const verticalClasses = `grid grid-rows-${verticalCount} gap-y-2`; + + const defaultParentClassNames = ""; // TODO: For later + const parentClassName = classNames.parent ?? defaultParentClassNames; + + return ( +
+ + +
+ ); +}; + +const SkeletonPerCount = ({ count, className }) => { + return ( + count > 0 && ( +
+ {range(0, count).map((index) => ( + + ))} +
+ ) + ); +}; diff --git a/src/index.js b/src/index.js index 73ecfbbe..2cecae48 100644 --- a/src/index.js +++ b/src/index.js @@ -33,7 +33,7 @@ export { Label } from "./components/Forms/Label"; export { RangeSlider } from "./components/Forms/RangeSlider"; export { HeaderToolbar } from "./components/HeaderToolbar"; export { Tabs } from "./components/Tabs"; -export { Skeleton } from "./components/Skeleton"; +export { Skeleton, SkeletonList } from "./components/Skeleton"; export { Drawer } from "./components/Drawer"; export { Key } from "./components/Key"; export { Login } from "./components/Screens/Login"; diff --git a/src/stories/DataDisplay/Skeleton.stories.js b/src/stories/DataDisplay/Skeleton.stories.js index 119c96fb..aae7d591 100644 --- a/src/stories/DataDisplay/Skeleton.stories.js +++ b/src/stories/DataDisplay/Skeleton.stories.js @@ -1,5 +1,5 @@ import React from "react"; -import { Skeleton } from "../.."; +import { Skeleton, SkeletonList } from "../.."; const SkeletonStories = { title: "Data Display/Skeleton", @@ -7,15 +7,38 @@ const SkeletonStories = { }; export const Default = () => { - return Loading...; + return ( +
+

+ Parent div set with w-full and h-75 (300px). No children specified so text + defaults to "Loading..." +

+ +
+ ); }; - -export const WithoutAnimation = () => { +export const CustomHeight = () => { return ( - - Not Available + + Height given directly to Skeleton using height attribute ); }; +export const MultipleSkeletons = () => { + return ( +
+

Quickly create multiple Skeleton children

+
+

A grid of 3x2 by passing in grid={[3x2]}

+ +
+
+

A grid of 2x4 by passing in grid={[2x4]}

+ +
+
+ ); +}; + export default SkeletonStories; diff --git a/tailwind.config.js b/tailwind.config.js index 3a6f1534..8013196e 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -136,6 +136,14 @@ module.exports = { spacing, + keyframes: { + shimmer: { + "100%": { + transform: "translateX(100%)", + }, + }, + }, + // Figma: https://www.figma.com/file/tL2vrxuBIzujkDfYvVjUhs/%F0%9F%9B%A0-Xola-DS-Desktop-Master-%F0%9F%9B%A0?node-id=1885%3A51905 fontSize: { xs: "10px", From b4e95e83a7dfc9bf95ba24bc2b5d413e1646bfc8 Mon Sep 17 00:00:00 2001 From: Rushi Vishavadia Date: Tue, 9 Aug 2022 08:14:11 +0400 Subject: [PATCH 2/8] #150 Skeleton with an icon so we can show placeholder images --- src/components/Skeleton.jsx | 9 ++++-- src/index.js | 2 +- src/stories/DataDisplay/Skeleton.stories.js | 33 +++++++++++++++++---- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/components/Skeleton.jsx b/src/components/Skeleton.jsx index 0b56ccc2..18c3fe15 100644 --- a/src/components/Skeleton.jsx +++ b/src/components/Skeleton.jsx @@ -1,7 +1,7 @@ import clsx from "clsx"; +import { range } from "lodash"; import PropTypes from "prop-types"; import React from "react"; -import { range, uniqueId } from "lodash"; export const Skeleton = ({ height = "h-full", children, className, ...rest }) => { return ( @@ -32,7 +32,7 @@ Skeleton.propTypes = { children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]), }; -export const SkeletonList = ({ grid = [3, 2], classNames = {} }) => { +export const SkeletonGrid = ({ grid = [3, 2], classNames = {} }) => { const [horizontalCount, verticalCount] = grid; const horizontalClasses = `grid grid-cols-${horizontalCount} gap-x-2`; const verticalClasses = `grid grid-rows-${verticalCount} gap-y-2`; @@ -59,3 +59,8 @@ const SkeletonPerCount = ({ count, className }) => { ) ); }; + +export const SkeletonIcon = ({ icon, classNames = { skeleton: "h-28 w-28", icon: "h-1/2 w-1/2 text-gray" } }) => { + const adjustedIcon = React.cloneElement(icon, { className: classNames.icon }); + return {adjustedIcon}; +}; diff --git a/src/index.js b/src/index.js index 2cecae48..5351bd1e 100644 --- a/src/index.js +++ b/src/index.js @@ -33,7 +33,7 @@ export { Label } from "./components/Forms/Label"; export { RangeSlider } from "./components/Forms/RangeSlider"; export { HeaderToolbar } from "./components/HeaderToolbar"; export { Tabs } from "./components/Tabs"; -export { Skeleton, SkeletonList } from "./components/Skeleton"; +export { Skeleton, SkeletonGrid, SkeletonIcon } from "./components/Skeleton"; export { Drawer } from "./components/Drawer"; export { Key } from "./components/Key"; export { Login } from "./components/Screens/Login"; diff --git a/src/stories/DataDisplay/Skeleton.stories.js b/src/stories/DataDisplay/Skeleton.stories.js index aae7d591..f230d4e3 100644 --- a/src/stories/DataDisplay/Skeleton.stories.js +++ b/src/stories/DataDisplay/Skeleton.stories.js @@ -1,5 +1,5 @@ import React from "react"; -import { Skeleton, SkeletonList } from "../.."; +import { Skeleton, SkeletonGrid, SkeletonIcon, ImageIcon, BarGraphIcon, MountainIcon } from "../.."; const SkeletonStories = { title: "Data Display/Skeleton", @@ -30,12 +30,35 @@ export const MultipleSkeletons = () => {

Quickly create multiple Skeleton children

-

A grid of 3x2 by passing in grid={[3x2]}

- +

+ A grid of 3x2 by passing in grid={[3x2]} +

+
-

A grid of 2x4 by passing in grid={[2x4]}

- +

+ A grid of 2x4 by passing in grid={[2x4]} +

+ +
+
+ ); +}; + +export const WithIcons = () => { + return ( +
+
+ Generic Image + } /> +
+
+ Experience Image + } /> +
+
+ Bar Graph + } />
); From 185d2051db31cd8022d31ccd45ad82120dc04816 Mon Sep 17 00:00:00 2001 From: Rushi Vishavadia Date: Tue, 9 Aug 2022 08:42:07 +0400 Subject: [PATCH 3/8] Add ability to override the horiz and vert skeletons --- src/components/Skeleton.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Skeleton.jsx b/src/components/Skeleton.jsx index 18c3fe15..c0ac184e 100644 --- a/src/components/Skeleton.jsx +++ b/src/components/Skeleton.jsx @@ -37,13 +37,13 @@ export const SkeletonGrid = ({ grid = [3, 2], classNames = {} }) => { const horizontalClasses = `grid grid-cols-${horizontalCount} gap-x-2`; const verticalClasses = `grid grid-rows-${verticalCount} gap-y-2`; - const defaultParentClassNames = ""; // TODO: For later + const defaultParentClassNames = "h-full"; const parentClassName = classNames.parent ?? defaultParentClassNames; return (
- - + +
); }; From b50fb2d39f4d85e933bd6e27c3ecaa7d35b89161 Mon Sep 17 00:00:00 2001 From: Rushi Vishavadia Date: Sat, 3 Sep 2022 15:09:15 +0530 Subject: [PATCH 4/8] Go back to the original skeleton shimmer --- src/components/Skeleton.jsx | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/components/Skeleton.jsx b/src/components/Skeleton.jsx index c0ac184e..0a580142 100644 --- a/src/components/Skeleton.jsx +++ b/src/components/Skeleton.jsx @@ -2,26 +2,23 @@ import clsx from "clsx"; import { range } from "lodash"; import PropTypes from "prop-types"; import React from "react"; +import styles from "./Skeleton.module.css"; -export const Skeleton = ({ height = "h-full", children, className, ...rest }) => { +export const Skeleton = ({ height = "h-full", children, className, classNames = {}, ...rest }) => { return (
- {children ?? "Loading..."} +
+
+ {children ?? "Loading..."} +
); }; @@ -32,10 +29,10 @@ Skeleton.propTypes = { children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]), }; -export const SkeletonGrid = ({ grid = [3, 2], classNames = {} }) => { +export const SkeletonGrid = ({ grid = [3, 2], classNames = { horizontal: "h-10", vertical: "!h-10" } }) => { const [horizontalCount, verticalCount] = grid; const horizontalClasses = `grid grid-cols-${horizontalCount} gap-x-2`; - const verticalClasses = `grid grid-rows-${verticalCount} gap-y-2`; + const verticalClasses = `grid grid-rows-${verticalCount - 1} gap-y-2`; const defaultParentClassNames = "h-full"; const parentClassName = classNames.parent ?? defaultParentClassNames; @@ -43,17 +40,21 @@ export const SkeletonGrid = ({ grid = [3, 2], classNames = {} }) => { return (
- +
); }; -const SkeletonPerCount = ({ count, className }) => { +const SkeletonPerCount = ({ count, className, classNames = {} }) => { return ( count > 0 && (
{range(0, count).map((index) => ( - + ))}
) From 52f57f2a45aeee0aa3d8688d6dfdeaf451f53099 Mon Sep 17 00:00:00 2001 From: Rushi Vishavadia Date: Sat, 3 Sep 2022 15:20:04 +0530 Subject: [PATCH 5/8] Allow user to override entire content --- src/components/Skeleton.jsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/Skeleton.jsx b/src/components/Skeleton.jsx index 0a580142..abef874e 100644 --- a/src/components/Skeleton.jsx +++ b/src/components/Skeleton.jsx @@ -16,9 +16,11 @@ export const Skeleton = ({ height = "h-full", children, className, classNames = {...rest} >
-
- {children ?? "Loading..."} -
+ {children ?? ( +
+ Loading... +
+ )}
); }; From 4ed66e7c2deac304f30943b32928f91ce67b6a23 Mon Sep 17 00:00:00 2001 From: Rushi Vishavadia Date: Sat, 3 Sep 2022 17:17:36 +0530 Subject: [PATCH 6/8] Stabilize Skeleton arch --- src/components/Skeleton.jsx | 51 ++++++++++++++++----- src/stories/DataDisplay/Skeleton.stories.js | 9 ++-- 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/components/Skeleton.jsx b/src/components/Skeleton.jsx index abef874e..c55538cd 100644 --- a/src/components/Skeleton.jsx +++ b/src/components/Skeleton.jsx @@ -4,7 +4,7 @@ import PropTypes from "prop-types"; import React from "react"; import styles from "./Skeleton.module.css"; -export const Skeleton = ({ height = "h-full", children, className, classNames = {}, ...rest }) => { +export const Skeleton = ({ height = "h-full", text, children, className, classNames = {}, ...rest }) => { return (
{children ?? (
- Loading... + {text ?? ""}
)}
@@ -31,21 +31,48 @@ Skeleton.propTypes = { children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]), }; -export const SkeletonGrid = ({ grid = [3, 2], classNames = { horizontal: "h-10", vertical: "!h-10" } }) => { - const [horizontalCount, verticalCount] = grid; - const horizontalClasses = `grid grid-cols-${horizontalCount} gap-x-2`; - const verticalClasses = `grid grid-rows-${verticalCount - 1} gap-y-2`; +const gridHorizontal = { + 1: "grid-cols-1", + 2: "grid-cols-2", + 3: "grid-cols-3", + 4: "grid-cols-4", + 5: "grid-cols-5", + 6: "grid-cols-6", + 7: "grid-cols-7", + 8: "grid-cols-8", +}; - const defaultParentClassNames = "h-full"; - const parentClassName = classNames.parent ?? defaultParentClassNames; +const gridVertical = { + 1: "grid-rows-1", + 2: "grid-rows-2", + 3: "grid-rows-3", + 4: "grid-rows-4", + 5: "grid-rows-5", + 6: "grid-rows-6", + 7: "grid-rows-7", + 8: "grid-rows-8", +}; + +export const SkeletonGrid = ({ + grid = [3, 2], + className = "h-full", + classNames = { horizontalContainer: "", verticalContainer: "", horizontal: "!h-10", vertical: "!h-10" }, +}) => { + const [horizontalCount, verticalCount] = grid; + const horizontalClasses = clsx("grid gap-x-2", gridHorizontal[horizontalCount] ?? `grid-cols-${horizontalCount}`); + const verticalClasses = clsx("grid gap-y-2", gridVertical[verticalCount] ?? `grid-rows-${verticalCount}`); return ( -
- +
+
); diff --git a/src/stories/DataDisplay/Skeleton.stories.js b/src/stories/DataDisplay/Skeleton.stories.js index f230d4e3..69a38ce3 100644 --- a/src/stories/DataDisplay/Skeleton.stories.js +++ b/src/stories/DataDisplay/Skeleton.stories.js @@ -10,10 +10,9 @@ export const Default = () => { return (

- Parent div set with w-full and h-75 (300px). No children specified so text - defaults to "Loading..." + Parent div set with w-full and h-75 (300px). No children specified

- +
); }; @@ -31,9 +30,9 @@ export const MultipleSkeletons = () => {

Quickly create multiple Skeleton children

- A grid of 3x2 by passing in grid={[3x2]} + A grid of 4x2 by passing in grid={[4x2]}

- +

From ed24fec33a0e38affcb6db1e690edf8de662f2cc Mon Sep 17 00:00:00 2001 From: Rushi Vishavadia Date: Sun, 13 Nov 2022 11:34:58 +0530 Subject: [PATCH 7/8] Rename component that's not actually an icon --- src/components/Skeleton.jsx | 5 ++++- src/index.js | 2 +- src/stories/DataDisplay/Skeleton.stories.js | 8 ++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/components/Skeleton.jsx b/src/components/Skeleton.jsx index c55538cd..03e5034c 100644 --- a/src/components/Skeleton.jsx +++ b/src/components/Skeleton.jsx @@ -90,7 +90,10 @@ const SkeletonPerCount = ({ count, className, classNames = {} }) => { ); }; -export const SkeletonIcon = ({ icon, classNames = { skeleton: "h-28 w-28", icon: "h-1/2 w-1/2 text-gray" } }) => { +export const SkeletonIconOnly = ({ icon, classNames = { skeleton: "h-28 w-28", icon: "h-1/2 w-1/2 text-gray" } }) => { + if (!icon) { + return null; + } const adjustedIcon = React.cloneElement(icon, { className: classNames.icon }); return {adjustedIcon}; }; diff --git a/src/index.js b/src/index.js index 6d8bf23d..2768b8d2 100644 --- a/src/index.js +++ b/src/index.js @@ -33,7 +33,7 @@ export { Label } from "./components/Forms/Label"; export { RangeSlider } from "./components/Forms/RangeSlider"; export { HeaderToolbar } from "./components/HeaderToolbar"; export { Tabs } from "./components/Tabs"; -export { Skeleton, SkeletonGrid, SkeletonIcon } from "./components/Skeleton"; +export { Skeleton, SkeletonGrid, SkeletonIconOnly } from "./components/Skeleton"; export { Drawer } from "./components/Drawer"; export { Key } from "./components/Key"; export { Login } from "./components/Screens/Login"; diff --git a/src/stories/DataDisplay/Skeleton.stories.js b/src/stories/DataDisplay/Skeleton.stories.js index 69a38ce3..7fc6ee2f 100644 --- a/src/stories/DataDisplay/Skeleton.stories.js +++ b/src/stories/DataDisplay/Skeleton.stories.js @@ -1,5 +1,5 @@ import React from "react"; -import { Skeleton, SkeletonGrid, SkeletonIcon, ImageIcon, BarGraphIcon, MountainIcon } from "../.."; +import { Skeleton, SkeletonGrid, SkeletonIconOnly, ImageIcon, BarGraphIcon, MountainIcon } from "../.."; const SkeletonStories = { title: "Data Display/Skeleton", @@ -49,15 +49,15 @@ export const WithIcons = () => {

Generic Image - } /> + } />
Experience Image - } /> + } />
Bar Graph - } /> + } />
); From ea9b034fa1fe64d8f7a720c39718ebd496466bd1 Mon Sep 17 00:00:00 2001 From: Rushi Vishavadia Date: Sun, 13 Nov 2022 11:37:27 +0530 Subject: [PATCH 8/8] =?UTF-8?q?=F0=9F=A7=B9=20Lint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Skeleton.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Skeleton.jsx b/src/components/Skeleton.jsx index 03e5034c..c56143c9 100644 --- a/src/components/Skeleton.jsx +++ b/src/components/Skeleton.jsx @@ -94,6 +94,7 @@ export const SkeletonIconOnly = ({ icon, classNames = { skeleton: "h-28 w-28", i if (!icon) { return null; } + const adjustedIcon = React.cloneElement(icon, { className: classNames.icon }); return {adjustedIcon}; };