From fc95e83e704ec054f551bae587a8a6e5bcaf4135 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Fri, 14 Aug 2020 15:36:17 +0300 Subject: feat: create Image and BackgroundImage components --- src/components/Image/Image.tsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/components/Image/Image.tsx (limited to 'src/components/Image/Image.tsx') diff --git a/src/components/Image/Image.tsx b/src/components/Image/Image.tsx new file mode 100644 index 0000000..de67c6a --- /dev/null +++ b/src/components/Image/Image.tsx @@ -0,0 +1,14 @@ +import React from 'react'; + +interface PropTypes { + src?: string; + alt?: string; + className?: string; +} + +const Image: React.FC = ({ src, alt, className }) => { + return {alt}; +}; + +export default Image; + -- cgit v1.2.3 From c5cacacfadf12c9321e932ce2fc3fa669b4c8807 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Fri, 14 Aug 2020 16:16:01 +0300 Subject: feat: handle loading and error states in Image --- src/components/Image/Image.tsx | 55 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) (limited to 'src/components/Image/Image.tsx') diff --git a/src/components/Image/Image.tsx b/src/components/Image/Image.tsx index de67c6a..7736e8a 100644 --- a/src/components/Image/Image.tsx +++ b/src/components/Image/Image.tsx @@ -1,4 +1,7 @@ -import React from 'react'; +import React, { useState, useCallback } from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import CircularProgress from '@material-ui/core/CircularProgress'; +import ErrorIcon from '@material-ui/icons/BrokenImage'; interface PropTypes { src?: string; @@ -6,8 +9,56 @@ interface PropTypes { className?: string; } +const useStyles = makeStyles(theme => ({ + container: { + width: '100%', + height: '100%', + display: 'flex', + alignItems: 'center', + justifyContent: 'center' + } +})); + +type Status = 'success' |'loading' | 'error'; + const Image: React.FC = ({ src, alt, className }) => { - return {alt}; + const classes = useStyles(); + const [status, setStatus] = useState('loading'); + + const handleLoad = useCallback((): void => { + setStatus('success'); + }, [setStatus]); + + const handleError = useCallback((): void => { + setStatus('error'); + }, [setStatus]); + + const image = ( + {alt} + ); + + return ( + <> + {src && image} + { + status !== 'success' && ( +
+ { + (status === 'error' || !src) + ? + : + } +
+ )} + + ); }; export default Image; -- cgit v1.2.3 From e8519bdddd31a33ace25ffbcb73273c1573e9c33 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Fri, 14 Aug 2020 16:51:19 +0300 Subject: feat: apply cool transitions to Image --- src/components/Image/Image.tsx | 55 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 10 deletions(-) (limited to 'src/components/Image/Image.tsx') diff --git a/src/components/Image/Image.tsx b/src/components/Image/Image.tsx index 7736e8a..1898716 100644 --- a/src/components/Image/Image.tsx +++ b/src/components/Image/Image.tsx @@ -1,14 +1,19 @@ -import React, { useState, useCallback } from 'react'; +import React, { useState, useCallback, useMemo } from 'react'; import { makeStyles } from '@material-ui/core/styles'; import CircularProgress from '@material-ui/core/CircularProgress'; import ErrorIcon from '@material-ui/icons/BrokenImage'; +import grey from '@material-ui/core/colors/grey'; interface PropTypes { src?: string; alt?: string; className?: string; + animationDuration?: number; + disableLoading?: boolean; } +type Status = 'success' | 'loading' | 'error'; + const useStyles = makeStyles(theme => ({ container: { width: '100%', @@ -16,12 +21,35 @@ const useStyles = makeStyles(theme => ({ display: 'flex', alignItems: 'center', justifyContent: 'center' + }, + success: { + opacity: '100%', + filterBrightness: '100%', + filterSaturate: '100%' + }, + loading: { + opacity: 0, + filterBrightness: 0, + filterSaturate: '20%', + position: 'absolute' + }, + error: { + display: 'none' + }, + errorIcon: { + color: grey[300], + width: theme.spacing(6), + height: theme.spacing(6) } })); -type Status = 'success' |'loading' | 'error'; - -const Image: React.FC = ({ src, alt, className }) => { +const Image: React.FC = React.memo(({ + src, + alt, + className, + animationDuration = 1000, + disableLoading = false +}) => { const classes = useStyles(); const [status, setStatus] = useState('loading'); @@ -33,12 +61,18 @@ const Image: React.FC = ({ src, alt, className }) => { setStatus('error'); }, [setStatus]); + const transition = useMemo(() => ` + filterBrightness ${animationDuration * 0.75}ms cubic-bezier(0.4, 0.0, 0.2, 1), + filterSaturate ${animationDuration}ms cubic-bezier(0.4, 0.0, 0.2, 1), + opacity ${animationDuration / 2}ms cubic-bezier(0.4, 0.0, 0.2, 1) + `, [animationDuration]); + const image = ( {alt} @@ -52,14 +86,15 @@ const Image: React.FC = ({ src, alt, className }) => {
{ (status === 'error' || !src) - ? - : + ? + : (!disableLoading && ) }
- )} + ) + } ); -}; +}); export default Image; -- cgit v1.2.3