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/BackgroundImage.tsx | 35 ++++++++++++++++++++++++++++++++ src/components/Image/Image.tsx | 14 +++++++++++++ src/components/PollCard/PollCard.tsx | 29 ++++++++------------------ 3 files changed, 58 insertions(+), 20 deletions(-) create mode 100644 src/components/Image/BackgroundImage.tsx create mode 100644 src/components/Image/Image.tsx (limited to 'src/components') diff --git a/src/components/Image/BackgroundImage.tsx b/src/components/Image/BackgroundImage.tsx new file mode 100644 index 0000000..824f667 --- /dev/null +++ b/src/components/Image/BackgroundImage.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import Image from './Image'; + +interface PropTypes { + src?: string; + alt?: string; +} + +const useStyles = makeStyles(theme => ({ + root: { + position: 'absolute', + width: '100%', + height: '100%' + }, + image: { + objectFit: 'cover', + pointerEvents: 'none', + width: '100%', + height: '100%' + } +})); + +const BackgroundImage: React.FC = ({ src, alt }) => { + const classes = useStyles(); + + return ( + + {alt} + + ) +} + +export default BackgroundImage; + 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; + diff --git a/src/components/PollCard/PollCard.tsx b/src/components/PollCard/PollCard.tsx index 689e872..a4c2144 100644 --- a/src/components/PollCard/PollCard.tsx +++ b/src/components/PollCard/PollCard.tsx @@ -1,15 +1,12 @@ import React from 'react'; import { makeStyles } from '@material-ui/core/styles'; -import { - Card, - CardActionArea, - CardMedia -} from '@material-ui/core/'; +import { Card, CardActionArea } from '@material-ui/core/'; import { Which, Poll } from 'which-types'; import { useSnackbar } from 'notistack'; import PercentageBar from './PercentageBar'; import UserStrip from '../UserStrip/UserStrip'; +import BackgroundImage from '../Image/BackgroundImage'; import { post } from '../../requests'; import { useAuth } from '../../hooks/useAuth'; @@ -27,12 +24,10 @@ const DATE_FORMAT = { }; const useStyles = makeStyles(theme => ({ - images: { + media: { + display: 'flex', height: theme.spacing(50) }, - imagesBlock: { - display: 'flex' - }, rateLine: { position: 'relative', width: '100%', @@ -101,19 +96,13 @@ const PollCard: React.FC = ({ poll, setPoll }) => { return ( -
- - +
+ + - - + +
-- 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') 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/BackgroundImage.tsx | 8 ++--- src/components/Image/Image.tsx | 55 ++++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 14 deletions(-) (limited to 'src/components') diff --git a/src/components/Image/BackgroundImage.tsx b/src/components/Image/BackgroundImage.tsx index 824f667..e749d10 100644 --- a/src/components/Image/BackgroundImage.tsx +++ b/src/components/Image/BackgroundImage.tsx @@ -7,7 +7,7 @@ interface PropTypes { alt?: string; } -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles({ root: { position: 'absolute', width: '100%', @@ -19,7 +19,7 @@ const useStyles = makeStyles(theme => ({ width: '100%', height: '100%' } -})); +}); const BackgroundImage: React.FC = ({ src, alt }) => { const classes = useStyles(); @@ -28,8 +28,8 @@ const BackgroundImage: React.FC = ({ src, alt }) => { {alt} - ) -} + ); +}; export default BackgroundImage; 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