From aa224c81018c4bc509bd2d7d425ec3e91365dc70 Mon Sep 17 00:00:00 2001 From: jindonyy Date: Tue, 1 Nov 2022 06:14:27 +0900 Subject: [PATCH 1/6] :sparkles: add Table component. --- src/components/common/Table/index.tsx | 155 ++++++++++++++++++ src/components/common/Table/table.stories.tsx | 61 +++++++ 2 files changed, 216 insertions(+) create mode 100644 src/components/common/Table/index.tsx create mode 100644 src/components/common/Table/table.stories.tsx diff --git a/src/components/common/Table/index.tsx b/src/components/common/Table/index.tsx new file mode 100644 index 0000000..5419480 --- /dev/null +++ b/src/components/common/Table/index.tsx @@ -0,0 +1,155 @@ +/* eslint-disable react/no-array-index-key */ +import { ReactNode, ReactElement, Children } from 'react'; +import { css, useTheme } from 'styled-components'; + +import Text, { TextSX } from '@components/common/Text'; +import { IPalette } from '@styles/theme'; + +type TableDefaultProps = { + children: ReactElement | ReactElement[]; +}; + +export interface TableProps extends TableDefaultProps { + caption: string; + cellWidth?: string[]; + children: ReactElement | ReactElement[]; +} + +const Table = ({ caption, cellWidth, children }: TableProps) => ( + `0.1rem solid ${theme.palette.borderLine}`}; + `} + > + + {cellWidth && ( + + {cellWidth?.map((width, index) => ( + + ))} + + )} + {children} +
+ {caption} +
+); + +const Thead = ({ children }: TableDefaultProps) => {children}; + +const Tbody = ({ children }: TableDefaultProps) => ( + theme.palette.hoverColor}; + } + `} + > + {children} + +); + +type TrSX = { + background?: keyof IPalette; +}; + +export interface TrProps extends TableDefaultProps { + sx?: TrSX; +} + +const Tr = ({ sx, children }: TrProps) => { + const theme = useTheme(); + + return ( + + {children} + + ); +}; + +type CellSX = { + width?: string; + justifyContent?: 'center' | 'flex-start'; + textOverflow?: 'ellipsis' | 'clip'; + whiteSpace?: 'nowrap' | 'normal'; +}; + +const defaultCellSX: TextSX = { + textAlign: 'center', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', +}; + +const cellCss = { + display: 'flex', + alignItems: 'center', + gap: '10px', + padding: '1.7rem 2rem', + overflow: 'hidden', +}; + +type ThProps = { + colSpan?: number; + sx?: CellSX; + children: ReactNode; +}; + +const Th = ({ sx, children, ...restProps }: ThProps) => ( + +
+ {Children.map(children, (child) => + typeof child === 'string' ? ( + + {child} + + ) : ( + child + ), + )} +
+ +); + +export interface TdProps extends ThProps { + rowSpan?: number; +} + +const Td = ({ sx, children, ...restProps }: TdProps) => ( + +
+ {Children.map(children, (child) => + typeof child === 'string' ? ( + + {child} + + ) : ( + child + ), + )} +
+ +); + +Table.Thead = Thead; +Table.Tbody = Tbody; +Table.Tr = Tr; +Table.Th = Th; +Table.Td = Td; + +export default Table; diff --git a/src/components/common/Table/table.stories.tsx b/src/components/common/Table/table.stories.tsx new file mode 100644 index 0000000..9a7939f --- /dev/null +++ b/src/components/common/Table/table.stories.tsx @@ -0,0 +1,61 @@ +import { ComponentStory, ComponentMeta } from '@storybook/react'; + +import Table from '@components/common/Table'; + +export default { + title: 'common/Table', + component: Table, +} as ComponentMeta; + +const noticeList = [ + { + id: 1, + title: '스터디 가입전 해당 공지사항을 숙지해주세요.', + writer: '파크', + date: '2022.10.22', + view: 101, + isFixed: true, + isNew: false, + }, + { + id: 2, + title: '스터디 전체 공지 드립니다.', + writer: '파크크크크', + date: '1시간 전', + view: 11, + isFixed: true, + isNew: true, + }, +]; + +export const Default: ComponentStory = () => ( + + + + 번호 + 제목 + 작성자 + 날짜 + 조회수 + + + + {noticeList.reverse().map(({ id, title, writer, date, view }) => ( + + {id} + {title} + + {writer} + arrow + + {date} + {view} + + ))} + +
+); From e7fc40432d557c88cfefd81da4bdb2c66b254f84 Mon Sep 17 00:00:00 2001 From: jindonyy Date: Wed, 2 Nov 2022 05:00:13 +0900 Subject: [PATCH 2/6] :wrench: add react/no-array-index-key option in eslintrc. --- .eslintrc.js | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintrc.js b/.eslintrc.js index 8112dc1..6c121be 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -53,6 +53,7 @@ module.exports = { 'react/react-in-jsx-scope': 'off', 'react/require-default-props': 'off', 'react/jsx-no-constructed-context-values': 'off', + 'react/no-array-index-key': 'off', 'import/order': [ 'error', { From 18bab6640387d8b485f975d87052c0178df50c3f Mon Sep 17 00:00:00 2001 From: jindonyy Date: Wed, 2 Nov 2022 05:02:39 +0900 Subject: [PATCH 3/6] :recycle: refact th, td component. remove code to devide child type. --- src/components/common/Table/index.tsx | 92 ++++++++------------------- 1 file changed, 26 insertions(+), 66 deletions(-) diff --git a/src/components/common/Table/index.tsx b/src/components/common/Table/index.tsx index 5419480..fbb785c 100644 --- a/src/components/common/Table/index.tsx +++ b/src/components/common/Table/index.tsx @@ -1,9 +1,8 @@ -/* eslint-disable react/no-array-index-key */ -import { ReactNode, ReactElement, Children } from 'react'; -import { css, useTheme } from 'styled-components'; +import { ReactNode, ReactElement, ComponentProps } from 'react'; +import { css } from 'styled-components'; -import Text, { TextSX } from '@components/common/Text'; -import { IPalette } from '@styles/theme'; +import FlexBox from '@components/common/FlexBox'; +import Text from '@components/common/Text'; type TableDefaultProps = { children: ReactElement | ReactElement[]; @@ -21,6 +20,7 @@ const Table = ({ caption, cellWidth, children }: TableProps) => ( width: 100%; overflow: hidden; border-top: ${({ theme }) => `0.1rem solid ${theme.palette.borderLine}`}; + table-layout: fixed; `} > ( ); -type TrSX = { - background?: keyof IPalette; -}; - -export interface TrProps extends TableDefaultProps { - sx?: TrSX; -} - -const Tr = ({ sx, children }: TrProps) => { - const theme = useTheme(); - - return ( - - {children} - - ); -}; +const Tr = ({ children }: TableDefaultProps) => ( + + `0.1rem solid ${theme.palette.borderLine}`}; + `} + > + {children} + +); type CellSX = { width?: string; justifyContent?: 'center' | 'flex-start'; - textOverflow?: 'ellipsis' | 'clip'; - whiteSpace?: 'nowrap' | 'normal'; }; -const defaultCellSX: TextSX = { - textAlign: 'center', - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', -}; - -const cellCss = { - display: 'flex', +const flexCss = { + justifyContent: 'center', alignItems: 'center', gap: '10px', - padding: '1.7rem 2rem', - overflow: 'hidden', -}; +} as Pick, 'sx'>; type ThProps = { colSpan?: number; @@ -110,19 +88,11 @@ type ThProps = { children: ReactNode; }; -const Th = ({ sx, children, ...restProps }: ThProps) => ( - -
- {Children.map(children, (child) => - typeof child === 'string' ? ( - - {child} - - ) : ( - child - ), - )} -
+const Th = ({ sx = {}, children, ...restProps }: ThProps) => ( + + + {children} + ); @@ -130,19 +100,9 @@ export interface TdProps extends ThProps { rowSpan?: number; } -const Td = ({ sx, children, ...restProps }: TdProps) => ( - -
- {Children.map(children, (child) => - typeof child === 'string' ? ( - - {child} - - ) : ( - child - ), - )} -
+const Td = ({ sx = {}, children, ...restProps }: TdProps) => ( + + {children} ); From ebd6ccdae12900953c752994f0d064d4923c85ff Mon Sep 17 00:00:00 2001 From: jindonyy Date: Wed, 2 Nov 2022 05:05:24 +0900 Subject: [PATCH 4/6] :white_check_mark: add MemberManagementList Table in storybook. --- src/components/common/Table/table.stories.tsx | 161 ++++++++++++++++-- 1 file changed, 147 insertions(+), 14 deletions(-) diff --git a/src/components/common/Table/table.stories.tsx b/src/components/common/Table/table.stories.tsx index 9a7939f..4a57af9 100644 --- a/src/components/common/Table/table.stories.tsx +++ b/src/components/common/Table/table.stories.tsx @@ -1,6 +1,8 @@ import { ComponentStory, ComponentMeta } from '@storybook/react'; +import Icon from '@components/common/Icon'; import Table from '@components/common/Table'; +import Text from '@components/common/Text'; export default { title: 'common/Table', @@ -16,19 +18,21 @@ const noticeList = [ view: 101, isFixed: true, isNew: false, + commentCount: 14, }, { id: 2, title: '스터디 전체 공지 드립니다.', - writer: '파크크크크', + writer: '파크크크크크크크크', date: '1시간 전', view: 11, isFixed: true, isNew: true, + commentCount: 0, }, ]; -export const Default: ComponentStory = () => ( +export const NoticeList: ComponentStory = () => ( @@ -40,20 +44,149 @@ export const Default: ComponentStory = () => ( - {noticeList.reverse().map(({ id, title, writer, date, view }) => ( - - {id} - {title} + {noticeList + .reverse() + .map(({ id, title, writer, date, view, commentCount }) => ( + + + {id} + + + {title} + {commentCount > 0 && ( + + {commentCount} + + )} + + + {writer} + + + {date} + + + {view} + + + ))} + +
+); + +const memberManagementList = [ + { + id: 1, + nickName: 'Hemdi', + status: 'waiting', + dateOfSubscription: '2022.10.22', + periodOfActivity: 0, + uncheckin: 0, + uncheckout: 0, + penaltyPoint: 0, + }, + { + id: 2, + nickName: 'Jamie', + status: 'warning', + dateOfSubscription: '2022.10.22', + periodOfActivity: 0, + uncheckin: 0, + uncheckout: 10, + penaltyPoint: 990, + }, + { + id: 3, + nickName: 'Park', + status: 'member', + dateOfSubscription: '2022.10.22', + periodOfActivity: 0, + uncheckin: 0, + uncheckout: 0, + penaltyPoint: 0, + }, +]; + +const STATUS = { + member: { + text: '활동 중', + color: 'primary', + }, + waiting: { + text: '가입 승인 대기 중', + color: 'fontColor', + }, + warning: { + text: '벌점 초과', + color: 'warning', + }, + danger: { + text: '경고 대상', + color: 'danger', + }, +}; + +export const MemberManagementList: ComponentStory = () => ( + + + + 닉네임 + 상태 + 가입일 + 활동일 + + 미 체크인 + + + + 미 체크아웃 + + + 벌점 + + + + {memberManagementList.map((props) => ( + + + + {props.nickName} + + + + + {STATUS[props.status].text} + + + + + {props.dateOfSubscription} + + + {props.periodOfActivity}일 + + + {props.uncheckin}회 + + + {props.uncheckout}회 + - {writer} - arrow + {props.penaltyPoint}점 - {date} - {view} ))} From d08b98aac9c75de1d5545ce16fa2c00e48cf66c9 Mon Sep 17 00:00:00 2001 From: jindonyy Date: Wed, 2 Nov 2022 06:06:19 +0900 Subject: [PATCH 5/6] :sparkles: add scope attribute in th element. --- src/components/common/Table/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/common/Table/index.tsx b/src/components/common/Table/index.tsx index fbb785c..bbc597e 100644 --- a/src/components/common/Table/index.tsx +++ b/src/components/common/Table/index.tsx @@ -89,7 +89,7 @@ type ThProps = { }; const Th = ({ sx = {}, children, ...restProps }: ThProps) => ( -
+ {children} From 2883113776ec66c4d8d171276f97b0311c1c2863 Mon Sep 17 00:00:00 2001 From: jindonyy Date: Fri, 4 Nov 2022 02:43:22 +0900 Subject: [PATCH 6/6] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20reflect=20the=20conten?= =?UTF-8?q?ts=20of=20the=20PR(#78).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - add offscreen style constant. - cellWidth -> columnsWidth - px -> rem - change Table children component naming - remove children type in TableProps --- src/components/common/Table/index.tsx | 35 ++---- src/components/common/Table/table.stories.tsx | 115 +++++++++--------- src/styles/commonStyles.ts | 10 ++ 3 files changed, 81 insertions(+), 79 deletions(-) create mode 100644 src/styles/commonStyles.ts diff --git a/src/components/common/Table/index.tsx b/src/components/common/Table/index.tsx index bbc597e..42a12f2 100644 --- a/src/components/common/Table/index.tsx +++ b/src/components/common/Table/index.tsx @@ -3,6 +3,7 @@ import { css } from 'styled-components'; import FlexBox from '@components/common/FlexBox'; import Text from '@components/common/Text'; +import { offscreen } from '@styles/commonStyles'; type TableDefaultProps = { children: ReactElement | ReactElement[]; @@ -10,11 +11,10 @@ type TableDefaultProps = { export interface TableProps extends TableDefaultProps { caption: string; - cellWidth?: string[]; - children: ReactElement | ReactElement[]; + columnsWidth?: string[]; } -const Table = ({ caption, cellWidth, children }: TableProps) => ( +const Table = ({ caption, columnsWidth, children }: TableProps) => ( ( table-layout: fixed; `} > - - {cellWidth && ( + + {columnsWidth && ( - {cellWidth?.map((width, index) => ( + {columnsWidth.map((width, index) => ( ))} @@ -79,7 +68,7 @@ type CellSX = { const flexCss = { justifyContent: 'center', alignItems: 'center', - gap: '10px', + gap: '1rem', } as Pick, 'sx'>; type ThProps = { @@ -106,10 +95,10 @@ const Td = ({ sx = {}, children, ...restProps }: TdProps) => ( ); -Table.Thead = Thead; -Table.Tbody = Tbody; -Table.Tr = Tr; -Table.Th = Th; -Table.Td = Td; +Table.Head = Thead; +Table.Body = Tbody; +Table.Row = Tr; +Table.HeadCell = Th; +Table.BodyCell = Td; export default Table; diff --git a/src/components/common/Table/table.stories.tsx b/src/components/common/Table/table.stories.tsx index 4a57af9..5532ae4 100644 --- a/src/components/common/Table/table.stories.tsx +++ b/src/components/common/Table/table.stories.tsx @@ -33,25 +33,28 @@ const noticeList = [ ]; export const NoticeList: ComponentStory = () => ( -
- {caption} - {caption}
- - - 번호 - 제목 - 작성자 - 날짜 - 조회수 - - - +
+ + + 번호 + 제목 + 작성자 + 날짜 + 조회수 + + + {noticeList .reverse() .map(({ id, title, writer, date, view, commentCount }) => ( - - + + {id} - - + = () => ( {commentCount} )} - - + + {writer} - - + + {date} - - + + {view} - - + + ))} - +
); @@ -136,33 +139,33 @@ const STATUS = { export const MemberManagementList: ComponentStory = () => ( - - - 닉네임 - 상태 - 가입일 - 활동일 - + + + 닉네임 + 상태 + 가입일 + 활동일 + 미 체크인 - - + + 미 체크아웃 - - 벌점 - - - + + 벌점 + + + {memberManagementList.map((props) => ( - - + + {props.nickName} - - + + = () => ( {STATUS[props.status].text} - - + + {props.dateOfSubscription} - - + + {props.periodOfActivity}일 - - + + {props.uncheckin}회 - - + + {props.uncheckout}회 - - + + {props.penaltyPoint}점 - - + + ))} - +
); diff --git a/src/styles/commonStyles.ts b/src/styles/commonStyles.ts new file mode 100644 index 0000000..2132695 --- /dev/null +++ b/src/styles/commonStyles.ts @@ -0,0 +1,10 @@ +import { CSSObject } from 'styled-components'; + +export const offscreen: CSSObject = { + position: 'absolute', + width: '1px', + height: '1px', + margin: '-1px', + overflow: 'hidden', + clipPath: 'polygon(0 0, 0 0, 0 0)', +};