From 64055efaf9e38547386db43512462d895b712a2c Mon Sep 17 00:00:00 2001 From: Hazem Krimi Date: Fri, 28 May 2021 17:41:21 +0100 Subject: [PATCH] Add image preview component --- src/components/ImagePreview/index.tsx | 53 ++++++++++++++ src/components/ImagePreview/styles.ts | 99 +++++++++++++++++++++++++++ src/components/index.tsx | 2 + 3 files changed, 154 insertions(+) create mode 100644 src/components/ImagePreview/index.tsx create mode 100644 src/components/ImagePreview/styles.ts diff --git a/src/components/ImagePreview/index.tsx b/src/components/ImagePreview/index.tsx new file mode 100644 index 0000000..9656dae --- /dev/null +++ b/src/components/ImagePreview/index.tsx @@ -0,0 +1,53 @@ +import { Wrapper } from './styles'; +import { Upload, Close } from '../../assets'; + +type ImagePreviewProps = { + className?: string; + color?: + | 'client' + | 'productOwner' + | 'developer' + | 'admin' + | 'success' + | 'warning' + | 'error' + | 'black' + | 'white'; + error?: boolean; + errorMessage?: string; + name?: string; + image: { name: string; src: string } | undefined; + deletable?: boolean; + onChange?: (event: React.ChangeEvent) => void; + onDelete?: () => void; +}; + +const ImagePreview = ({ + name, + image, + deletable = false, + onChange, + onDelete, + ...props +}: ImagePreviewProps) => { + return ( + + {image ? ( +
+ {deletable && ( +
+ +
+ )} +
+ ) : ( +
+ + +
+ )} +
+ ); +}; + +export default ImagePreview; diff --git a/src/components/ImagePreview/styles.ts b/src/components/ImagePreview/styles.ts new file mode 100644 index 0000000..755f689 --- /dev/null +++ b/src/components/ImagePreview/styles.ts @@ -0,0 +1,99 @@ +import styled, { css } from 'styled-components'; + +type WrapperProps = { + color?: + | 'client' + | 'productOwner' + | 'developer' + | 'admin' + | 'success' + | 'warning' + | 'error' + | 'black' + | 'white'; + error?: boolean; + deletable?: boolean; + image: { name: string; src: string } | undefined; +}; + +export const Wrapper = styled.div` + .preview { + width: 175px; + height: 325px; + background: url(${({ image }) => image?.src}); + background-repeat: no-repeat; + background-size: contain; + background-position: center; + padding: 150px 30px; + position: relative; + + &:hover { + ${({ deletable, color, theme }) => + deletable && + css` + border: 2px solid ${theme.colors[color || 'client'].main}; + `} + + .close { + display: block; + } + } + + .close { + background: ${({ color, theme }) => theme.colors[color || 'client'].main}; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + position: absolute; + top: -11.5px; + right: -11.5px; + padding: 5px; + cursor: pointer; + display: none; + + svg { + width: 15px; + height: 15px; + stroke: ${({ theme }) => theme.colors.white.main}; + display: flex; + align-items: center; + justify-content: center; + } + } + } + + .upload { + padding: 150px 30px; + position: relative; + border: 2px solid + ${({ color, theme }) => theme.colors[color || 'client'].main}; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + + input { + opacity: 0; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + cursor: pointer; + + &::-webkit-file-upload-button { + display: none; + } + } + + svg { + width: 25px; + height: 25px; + + path { + stroke: ${({ color, theme }) => theme.colors[color || 'client'].main}; + } + } + } +`; diff --git a/src/components/index.tsx b/src/components/index.tsx index b9f9f12..4ff402b 100644 --- a/src/components/index.tsx +++ b/src/components/index.tsx @@ -20,6 +20,7 @@ import AuthRoute from './AuthRoute'; import SectionSelector from './SectionSelector'; import Modal from './Modal'; import SidebarItem from './SidebarItem'; +import ImagePreview from './ImagePreview'; export { Button, @@ -44,4 +45,5 @@ export { SectionSelector, Modal, SidebarItem, + ImagePreview, };