瀏覽代碼

add animated loader and error components (#1013)

* add animated loader and error components

* add className
Klaudiusz Dembler 3 年之前
父節點
當前提交
8fe68d1d11

+ 2 - 2
.prettierignore

@@ -8,5 +8,5 @@ public/mockServiceWorker.js
 .history
 docs/
 
-# Ignore animations as they become huge
-src/shared/animations
+# don't prettify minified animation JSONs
+src/shared/assets/animations

文件差異過大導致無法顯示
+ 0 - 0
src/shared/animations/loader-XL.json


文件差異過大導致無法顯示
+ 0 - 0
src/shared/assets/animations/error.json


+ 0 - 0
src/shared/animations/loader-L.json → src/shared/assets/animations/loader-L.json


+ 0 - 0
src/shared/animations/loader-M.json → src/shared/assets/animations/loader-M.json


+ 0 - 0
src/shared/animations/loader-S.json → src/shared/assets/animations/loader-S.json


+ 0 - 0
src/shared/animations/loader-XS.json → src/shared/assets/animations/loader-XS.json


文件差異過大導致無法顯示
+ 0 - 0
src/shared/assets/animations/loader-player.json


+ 12 - 0
src/shared/components/AnimatedError/AnimatedError.tsx

@@ -0,0 +1,12 @@
+import React from 'react'
+import Lottie from 'react-lottie-player'
+
+import errorAnimation from '../../assets/animations/error.json'
+
+type AnimatedErrorProps = {
+  className?: string
+}
+
+export const AnimatedError: React.FC<AnimatedErrorProps> = ({ className }) => {
+  return <Lottie play loop={false} animationData={errorAnimation} className={className} />
+}

+ 1 - 0
src/shared/components/AnimatedError/index.ts

@@ -0,0 +1 @@
+export * from './AnimatedError'

+ 38 - 0
src/shared/components/Loader/Loader.tsx

@@ -0,0 +1,38 @@
+import styled from '@emotion/styled'
+import React from 'react'
+import Lottie from 'react-lottie-player'
+
+import loaderLargeAnimation from '../../assets/animations/loader-L.json'
+import loaderMediumAnimation from '../../assets/animations/loader-M.json'
+import loaderSmallAnimation from '../../assets/animations/loader-S.json'
+import LoaderXSmallAnimation from '../../assets/animations/loader-XS.json'
+import loaderPlayerAnimation from '../../assets/animations/loader-player.json'
+
+type LoaderVariant = 'xlarge' | 'large' | 'medium' | 'small' | 'xsmall' | 'player'
+type LoaderProps = {
+  variant?: LoaderVariant
+  className?: string
+}
+type LoaderConfig = {
+  data: object
+  size: number
+}
+
+const VARIANT_TO_CONFIG: Record<LoaderVariant, LoaderConfig> = {
+  xlarge: { data: loaderLargeAnimation, size: 216 },
+  large: { data: loaderLargeAnimation, size: 108 },
+  medium: { data: loaderMediumAnimation, size: 36 },
+  small: { data: loaderSmallAnimation, size: 24 },
+  xsmall: { data: LoaderXSmallAnimation, size: 16 },
+  player: { data: loaderPlayerAnimation, size: 72 },
+}
+
+export const Loader: React.FC<LoaderProps> = ({ variant = 'medium', className }) => {
+  const config = VARIANT_TO_CONFIG[variant]
+  return <StyledLottie play animationData={config.data} $size={config.size} className={className} />
+}
+
+const StyledLottie = styled(Lottie)<{ $size: number }>`
+  width: ${({ $size }) => `${$size}px`};
+  height: ${({ $size }) => `${$size}px`};
+`

+ 1 - 0
src/shared/components/Loader/index.ts

@@ -0,0 +1 @@
+export * from './Loader'

+ 2 - 0
src/shared/components/index.ts

@@ -41,3 +41,5 @@ export * from './ExpandButton'
 export * from './Snackbar'
 export * from './HelperText'
 export * from './LegalText'
+export * from './Loader'
+export * from './AnimatedError'

+ 14 - 29
src/views/playground/Playgrounds/Animations.tsx

@@ -1,41 +1,26 @@
 import styled from '@emotion/styled'
-import loadable from '@loadable/component'
-import React, { useEffect, useState } from 'react'
+import React from 'react'
 
-const LoadableLottie = loadable(() => import('react-lottie-player'), {
-  fallback: <>LOADING LOTTIE</>,
-})
-export const Animations = () => {
-  const [XL, setXL] = useState<object | undefined>()
-  const [L, setL] = useState<object | undefined>()
-  const [M, setM] = useState<object | undefined>()
-  const [S, setS] = useState<object | undefined>()
-  const [XS, setXS] = useState<object | undefined>()
-
-  useEffect(() => {
-    import('@/shared/animations/loader-XL.json').then((loader) => setXL(loader.default))
-    import('@/shared/animations/loader-L.json').then((loader) => setL(loader.default))
-    import('@/shared/animations/loader-M.json').then((loader) => setM(loader.default))
-    import('@/shared/animations/loader-S.json').then((loader) => setS(loader.default))
-    import('@/shared/animations/loader-XS.json').then((loader) => setXS(loader.default))
-  }, [])
+import { AnimatedError, Loader } from '@/shared/components'
 
+export const Animations = () => {
   return (
     <Container>
-      ANIMATIONS
-      <LoadableLottie loop play animationData={XL} />
-      <LoadableLottie loop play animationData={L} />
-      <LoadableLottie loop play animationData={M} />
-      <LoadableLottie loop play animationData={S} />
-      <LoadableLottie loop play animationData={XS} />
+      <Loader variant="xlarge" />
+      <Loader variant="large" />
+      <Loader variant="medium" />
+      <Loader variant="small" />
+      <Loader variant="xsmall" />
+      <Loader variant="player" />
+      <AnimatedError />
     </Container>
   )
 }
 
 const Container = styled.div`
-  display: grid;
-  grid-gap: 32px;
+  display: flex;
+  flex-direction: column;
+  align-items: start;
+  gap: 32px;
   justify-content: center;
-  text-align: center;
-  grid-template-rows: auto 1fr 1fr 64px 32px 48px 48px;
 `

部分文件因文件數量過多而無法顯示