From bfbdb23c70bfdc57f8dead8e94159418bb8ff2d7 Mon Sep 17 00:00:00 2001 From: sonnguyenkieio Date: Thu, 9 Sep 2021 08:24:47 +0700 Subject: [PATCH] :sparkles: feat: Skeleton Common --- .../SkeletonCommon/SkeletonCommon.module.scss | 32 ++++++++++++ .../common/SkeletonCommon/SkeletonCommon.tsx | 17 +++++++ .../SkeletonAvatar/SkeletonAvatar.module.scss | 51 +++++++++++++++++++ .../SkeletonAvatar/SkeletonAvatar.tsx | 25 +++++++++ .../SkeletonParagraph.module.scss | 41 +++++++++++++++ .../SkeletonParagraph/SkeletonParagraph.tsx | 30 +++++++++++ .../SkeletonTitle/SkeletonTitle.module.scss | 27 ++++++++++ .../SkeletonTitle/SkeletonTitle.tsx | 28 ++++++++++ 8 files changed, 251 insertions(+) create mode 100644 src/components/common/SkeletonCommon/SkeletonCommon.module.scss create mode 100644 src/components/common/SkeletonCommon/SkeletonCommon.tsx create mode 100644 src/components/common/SkeletonCommon/components/SkeletonAvatar/SkeletonAvatar.module.scss create mode 100644 src/components/common/SkeletonCommon/components/SkeletonAvatar/SkeletonAvatar.tsx create mode 100644 src/components/common/SkeletonCommon/components/SkeletonParagraph/SkeletonParagraph.module.scss create mode 100644 src/components/common/SkeletonCommon/components/SkeletonParagraph/SkeletonParagraph.tsx create mode 100644 src/components/common/SkeletonCommon/components/SkeletonTitle/SkeletonTitle.module.scss create mode 100644 src/components/common/SkeletonCommon/components/SkeletonTitle/SkeletonTitle.tsx diff --git a/src/components/common/SkeletonCommon/SkeletonCommon.module.scss b/src/components/common/SkeletonCommon/SkeletonCommon.module.scss new file mode 100644 index 000000000..e388525e5 --- /dev/null +++ b/src/components/common/SkeletonCommon/SkeletonCommon.module.scss @@ -0,0 +1,32 @@ +@import '../../../styles/utilities'; + +$base-color: #ddd; +$shine-color: #e8e8e8; +$animation-duration: 1.6s; + +@mixin background-gradient { + background-image: linear-gradient(90deg, $base-color 0px, $shine-color 40px, $base-color 80px) ; + background-size: 600px; +} + +.skeletonCommon:empty { + margin: auto; + height: 14rem; + width: 14rem; + animation: name duration timing-function delay iteration-count direction fill-mode; + + @include background-gradient; + animation: shine-lines $animation-duration infinite linear; +} + +@keyframes shine-lines { + 0% { + background-position: -100px; + } + 40% { + background-position: 140px; + } + 100% { + background-position: 140px; + } +} \ No newline at end of file diff --git a/src/components/common/SkeletonCommon/SkeletonCommon.tsx b/src/components/common/SkeletonCommon/SkeletonCommon.tsx new file mode 100644 index 000000000..6b0631aef --- /dev/null +++ b/src/components/common/SkeletonCommon/SkeletonCommon.tsx @@ -0,0 +1,17 @@ +import React from "react"; +import s from './SkeletonCommon.module.scss' + +interface SkeletonCommonProps { + children? : React.ReactNode; +} + +const SkeletonCommon = ({ children }: SkeletonCommonProps) => { + + return ( +
+ {children} +
+ ) +} + +export default SkeletonCommon \ No newline at end of file diff --git a/src/components/common/SkeletonCommon/components/SkeletonAvatar/SkeletonAvatar.module.scss b/src/components/common/SkeletonCommon/components/SkeletonAvatar/SkeletonAvatar.module.scss new file mode 100644 index 000000000..82286d7a0 --- /dev/null +++ b/src/components/common/SkeletonCommon/components/SkeletonAvatar/SkeletonAvatar.module.scss @@ -0,0 +1,51 @@ +@import '../../../../../styles/utilities'; + +$base-color: #8F8F8F; +$shine-color: #ebebeb; +$animation-duration: 1.6s; +$avatar-offset: 52 + 16; + +@mixin background-gradient { + background-image: linear-gradient(90deg, $base-color 0px, $shine-color 40px, $base-color 80px) ; + background-size: 600px; +} + +.skeletonAvatar { + + &.active { + @include background-gradient; + animation: shine-avatar $animation-duration infinite linear; + } + + &.circle { + border-radius: 50%; + } + + &.square { + border-radius: 0; + } + + &.small { + width: 3.2rem; + height: 3.2rem; + } + &.default { + width: 4.8rem; + height: 4.8rem; + } + &.large { + width: 6.4rem; + height: 6.4rem; + } +} + +@keyframes shine-avatar { + 0% { + background-position: -100px + $avatar-offset + } + + 40%, 100% { + background-position: 140px + $avatar-offset + } + +} diff --git a/src/components/common/SkeletonCommon/components/SkeletonAvatar/SkeletonAvatar.tsx b/src/components/common/SkeletonCommon/components/SkeletonAvatar/SkeletonAvatar.tsx new file mode 100644 index 000000000..d5d20165b --- /dev/null +++ b/src/components/common/SkeletonCommon/components/SkeletonAvatar/SkeletonAvatar.tsx @@ -0,0 +1,25 @@ +import classNames from "classnames"; +import React from "react"; +import s from './SkeletonAvatar.module.scss' + +interface SkeletonAvatarProps { + active?: boolean, + shape?: "circle" | "square", + size?: "small" | "default" | "large", + children: React.ReactNode +} + +const SkeletonAvatar = ({ active=true, shape="circle", size="default", children }: SkeletonAvatarProps) => { + + return ( +
+ {children} +
+ ) +} + +export default SkeletonAvatar \ No newline at end of file diff --git a/src/components/common/SkeletonCommon/components/SkeletonParagraph/SkeletonParagraph.module.scss b/src/components/common/SkeletonCommon/components/SkeletonParagraph/SkeletonParagraph.module.scss new file mode 100644 index 000000000..259c1574c --- /dev/null +++ b/src/components/common/SkeletonCommon/components/SkeletonParagraph/SkeletonParagraph.module.scss @@ -0,0 +1,41 @@ +@import '../../../../../styles/utilities'; + +$base-color: #DDD; +$shine-color: #ebebeb; +$animation-duration: 2s; + +@mixin background-gradient { + background-image: linear-gradient(90deg, $base-color 0px, $shine-color 40px, $base-color 80px) ; + background-size: 100%; +} + +.skeletonParagraph { + @apply bg-white; + height: fit-content; + width: 100%; + + .row { + height: 2rem; + margin: 1rem; + animation: shine-lines $animation-duration infinite linear; + @include background-gradient; + } + + .lastRow { + height: 2rem; + margin: 1rem; + width: 85%; + animation: shine-lines $animation-duration infinite linear; + @include background-gradient; + } +} + +@keyframes shine-lines { + 0% { + background-position: -100px; + } + 40%, 100% { + background-position: 100%; + } +} + diff --git a/src/components/common/SkeletonCommon/components/SkeletonParagraph/SkeletonParagraph.tsx b/src/components/common/SkeletonCommon/components/SkeletonParagraph/SkeletonParagraph.tsx new file mode 100644 index 000000000..5c3620f0a --- /dev/null +++ b/src/components/common/SkeletonCommon/components/SkeletonParagraph/SkeletonParagraph.tsx @@ -0,0 +1,30 @@ +import classNames from "classnames"; +import React from "react"; +import s from './SkeletonParagraph.module.scss' + +interface SkeletonParagraphProps { + active?: boolean, + rows?: number // number of rows in paragraph + children: React.ReactNode +} + +const SkeletonParagraph = ({ active=true, rows=2, children }: SkeletonParagraphProps) => { + + return ( +
+ { + [...Array(rows)].map((e, i) => { + if (i === rows-1) { + return

+ } + return

+ }) + } + {children} +
+ ) +} + +export default SkeletonParagraph \ No newline at end of file diff --git a/src/components/common/SkeletonCommon/components/SkeletonTitle/SkeletonTitle.module.scss b/src/components/common/SkeletonCommon/components/SkeletonTitle/SkeletonTitle.module.scss new file mode 100644 index 000000000..0dbb139d3 --- /dev/null +++ b/src/components/common/SkeletonCommon/components/SkeletonTitle/SkeletonTitle.module.scss @@ -0,0 +1,27 @@ +@import '../../../../../styles/utilities'; + +$base-color: #8F8F8F; +$shine-color: #ebebeb; +$animation-duration: 1.6s; + +@mixin background-gradient { + background-image: linear-gradient(90deg, $base-color 0px, $shine-color 40px, $base-color 80px) ; + background-size: 600px; +} + +.skeletonTitle { + &.active { + @include background-gradient; + animation: shine-lines $animation-duration infinite linear; + } +} + +@keyframes shine-lines { + 0% { + background-position: -100px; + } + 40%, 100% { + background-position: 50rem; + } +} + diff --git a/src/components/common/SkeletonCommon/components/SkeletonTitle/SkeletonTitle.tsx b/src/components/common/SkeletonCommon/components/SkeletonTitle/SkeletonTitle.tsx new file mode 100644 index 000000000..40d747d8f --- /dev/null +++ b/src/components/common/SkeletonCommon/components/SkeletonTitle/SkeletonTitle.tsx @@ -0,0 +1,28 @@ +import classNames from "classnames"; +import React from "react"; +import s from './SkeletonTitle.module.scss' + +interface SkeletonTitleProps { + active?: boolean, + width: string | number, // number px + height: string | number, + children: React.ReactNode +} + +const SkeletonTitle = ({ active=true, width, height, children }: SkeletonTitleProps) => { + + const styles = { + width: width, + height: height + } + + return ( +
+ {children} +
+ ) +} + +export default SkeletonTitle \ No newline at end of file