From 5b470af3060ba8b27f23924dc8bec2b97422e738 Mon Sep 17 00:00:00 2001 From: dlwl98 Date: Fri, 27 Oct 2023 16:46:20 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20Image=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/shared/Image/Image.styles.ts | 12 +++++++ src/components/shared/Image/Image.tsx | 40 +++++++++++++++++++++ src/components/shared/Image/index.ts | 1 + 3 files changed, 53 insertions(+) create mode 100644 src/components/shared/Image/Image.styles.ts create mode 100644 src/components/shared/Image/Image.tsx create mode 100644 src/components/shared/Image/index.ts diff --git a/src/components/shared/Image/Image.styles.ts b/src/components/shared/Image/Image.styles.ts new file mode 100644 index 00000000..a081f0c5 --- /dev/null +++ b/src/components/shared/Image/Image.styles.ts @@ -0,0 +1,12 @@ +import styled from '@emotion/styled'; + +import { ImageCustomProps } from './Image'; + +type ImgProps = Required; + +export const Img = styled.img` + display: ${({ block }) => (block ? 'block' : 'inline')}; + width: ${({ width }) => width}; + height: ${({ height }) => height}; + object-fit: ${({ mode }) => mode}; +`; diff --git a/src/components/shared/Image/Image.tsx b/src/components/shared/Image/Image.tsx new file mode 100644 index 00000000..b03c24e0 --- /dev/null +++ b/src/components/shared/Image/Image.tsx @@ -0,0 +1,40 @@ +import { CSSProperties, HTMLAttributes } from 'react'; + +import { Img } from './Image.styles'; + +export type ImageCustomProps = { + src: string; + block?: boolean; + width: number | string; + height?: number | string; + alt: string; + mode?: CSSProperties['objectFit']; +}; +type ImageProps = ImageCustomProps & HTMLAttributes; + +export const Image = ({ + src, + block = false, + width, + height = width, + alt, + mode = 'cover', + ...props +}: ImageProps) => { + const stringifiedWidth = + typeof width === 'number' ? `${width / 16}rem` : width; + const stringifiedHeight = + typeof height === 'number' ? `${height / 16}rem` : height; + + return ( + {alt} + ); +}; diff --git a/src/components/shared/Image/index.ts b/src/components/shared/Image/index.ts new file mode 100644 index 00000000..4bbac901 --- /dev/null +++ b/src/components/shared/Image/index.ts @@ -0,0 +1 @@ +export * from './Image'; From 36b2942b229f4f5114c85b18e6e0d048da2a3016 Mon Sep 17 00:00:00 2001 From: dlwl98 Date: Fri, 27 Oct 2023 16:46:41 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20Avatar=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/shared/Avatar/Avatar.styles.ts | 10 +++++++ src/components/shared/Avatar/Avatar.tsx | 30 +++++++++++++++++++ src/components/shared/Avatar/index.ts | 1 + 3 files changed, 41 insertions(+) create mode 100644 src/components/shared/Avatar/Avatar.styles.ts create mode 100644 src/components/shared/Avatar/Avatar.tsx create mode 100644 src/components/shared/Avatar/index.ts diff --git a/src/components/shared/Avatar/Avatar.styles.ts b/src/components/shared/Avatar/Avatar.styles.ts new file mode 100644 index 00000000..e374695c --- /dev/null +++ b/src/components/shared/Avatar/Avatar.styles.ts @@ -0,0 +1,10 @@ +import styled from '@emotion/styled'; + +import { Image } from '@components/shared/Image'; + +import { AvatarProps } from './Avatar'; + +export const StyledImage = styled(Image)` + border: ${({ border }) => border}; + border-radius: ${({ radius }) => radius}; +`; diff --git a/src/components/shared/Avatar/Avatar.tsx b/src/components/shared/Avatar/Avatar.tsx new file mode 100644 index 00000000..c417a292 --- /dev/null +++ b/src/components/shared/Avatar/Avatar.tsx @@ -0,0 +1,30 @@ +import { StyledImage } from './Avatar.styles'; + +export type AvatarProps = { + src: string; + size?: number; + radius?: string; + border?: string; + style?: React.CSSProperties; +}; + +export const Avatar = ({ + src, + size = 30, + radius = '50%', + border, + style, + ...props +}: AvatarProps) => { + return ( + + ); +}; diff --git a/src/components/shared/Avatar/index.ts b/src/components/shared/Avatar/index.ts new file mode 100644 index 00000000..27700fe3 --- /dev/null +++ b/src/components/shared/Avatar/index.ts @@ -0,0 +1 @@ +export * from './Avatar'; From fbcb46662a18fa1ffc42ff7da31ae7a62d4614a3 Mon Sep 17 00:00:00 2001 From: dlwl98 Date: Fri, 27 Oct 2023 16:46:59 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20AvatarGroup=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shared/AvatarGroup/AvatarGroup.styles.ts | 17 +++++++ .../shared/AvatarGroup/AvatarGroup.tsx | 45 +++++++++++++++++++ src/components/shared/AvatarGroup/index.ts | 1 + 3 files changed, 63 insertions(+) create mode 100644 src/components/shared/AvatarGroup/AvatarGroup.styles.ts create mode 100644 src/components/shared/AvatarGroup/AvatarGroup.tsx create mode 100644 src/components/shared/AvatarGroup/index.ts diff --git a/src/components/shared/AvatarGroup/AvatarGroup.styles.ts b/src/components/shared/AvatarGroup/AvatarGroup.styles.ts new file mode 100644 index 00000000..92e17d78 --- /dev/null +++ b/src/components/shared/AvatarGroup/AvatarGroup.styles.ts @@ -0,0 +1,17 @@ +import styled from '@emotion/styled'; + +import { Avatar, AvatarProps } from '@components/shared/Avatar'; + +import { AvatarGroupProps } from './AvatarGroup'; + +type AvatarGroupWrapperProps = Required>; + +export const AvatarGroupWrapper = styled.div` + padding-left: ${({ overlap }) => `${overlap / 16}rem`}; +`; + +export const OverlapedAvatar = styled(Avatar)< + AvatarProps & { overlap: number } +>` + margin-left: ${({ overlap }) => `-${overlap / 16}rem`}; +`; diff --git a/src/components/shared/AvatarGroup/AvatarGroup.tsx b/src/components/shared/AvatarGroup/AvatarGroup.tsx new file mode 100644 index 00000000..5cca2b79 --- /dev/null +++ b/src/components/shared/AvatarGroup/AvatarGroup.tsx @@ -0,0 +1,45 @@ +import React, { HTMLAttributes } from 'react'; + +import { Avatar, AvatarProps } from '../Avatar'; +import { AvatarGroupWrapper, OverlapedAvatar } from './AvatarGroup.styles'; + +export type AvatarGroupProps = { + children: React.ReactNode; + overlap?: number; +} & Omit & + HTMLAttributes; + +export const AvatarGroup = ({ + children, + size = 30, + radius = '50%', + border, + overlap = 10, + ...props +}: AvatarGroupProps) => { + const avatars = React.Children.toArray(children) + .filter((element): element is React.ReactElement => { + if (!React.isValidElement(element)) { + return false; + } + if (element.type !== Avatar) { + return false; + } + return true; + }) + .map(({ props: { src } }) => ( + + )); + + return ( + + {avatars} + + ); +}; diff --git a/src/components/shared/AvatarGroup/index.ts b/src/components/shared/AvatarGroup/index.ts new file mode 100644 index 00000000..73dc5e1a --- /dev/null +++ b/src/components/shared/AvatarGroup/index.ts @@ -0,0 +1 @@ +export * from './AvatarGroup'; From 99e7d256c8276a2e80284757bc0fd0f8740ea292 Mon Sep 17 00:00:00 2001 From: dlwl98 Date: Sat, 28 Oct 2023 21:38:15 +0900 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20Avatar=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=EA=B0=80=20img=20element=20props=EB=A5=BC=20?= =?UTF-8?q?=EB=B0=9B=EB=8A=94=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/shared/Avatar/Avatar.tsx | 7 +++---- src/components/shared/AvatarGroup/AvatarGroup.tsx | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/components/shared/Avatar/Avatar.tsx b/src/components/shared/Avatar/Avatar.tsx index c417a292..961588d8 100644 --- a/src/components/shared/Avatar/Avatar.tsx +++ b/src/components/shared/Avatar/Avatar.tsx @@ -1,3 +1,5 @@ +import { HTMLAttributes } from 'react'; + import { StyledImage } from './Avatar.styles'; export type AvatarProps = { @@ -5,20 +7,17 @@ export type AvatarProps = { size?: number; radius?: string; border?: string; - style?: React.CSSProperties; -}; +} & HTMLAttributes; export const Avatar = ({ src, size = 30, radius = '50%', border, - style, ...props }: AvatarProps) => { return ( ( + .map(({ props }) => (