diff --git a/.changeset/sharp-walls-happen.md b/.changeset/sharp-walls-happen.md new file mode 100644 index 00000000..b2556451 --- /dev/null +++ b/.changeset/sharp-walls-happen.md @@ -0,0 +1,5 @@ +--- +"@musma/react-component": patch +--- + +feat: Flex Box diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..9bdd65cc --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,30 @@ +--- +name: "BUG \b템플릿" +about: 어떤 버그를 수정할 예정인가요? (버그의 예상 원인, 해결 방법 등등) +title: '[BUG]' +labels: '' +assignees: '' +--- + +## :fire: Description + +_어떤 버그를 수정할 예정인가요? (버그의 예상 원인, 해결 방법 등등)_ + +
+ +## :hammer: TODO + +- [ ] 할일1 +- [ ] 할일2 + +
+ +## :books: Reference + +_버그 픽스에 참고한 내용이 있나요? (블로그, 공식문서 등등)_ + +
+ +## :bell: ETC + +_메모할 사항이 있나요? (다른 개발자가 봤을 때 참고하면 좋을 내용, PR에 전달할 내용 등등)_ diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..3ba13e0c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: false diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..ef0718f3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,30 @@ +--- +name: "FEATURE \b템플릿" +about: 어떤 기능을 만드나요? (기능 설명, 목표 등등) +title: '[FEATURE]' +labels: '' +assignees: '' +--- + +## :mag: Description + +_어떤 기능을 만드나요? (기능 설명, 목표 등등)_ + +
+ +## :hammer: TODO + +- [ ] 할일1 +- [ ] 할일2 + +
+ +## :books: Reference + +_기능 구현에 참고한 내용이 있나요? (블로그, 공식문서 등등)_ + +
+ +## :bell: ETC + +_메모할 사항이 있나요? (다른 개발자가 봤을 때 참고하면 좋을 내용, PR에 전달할 내용 등등)_ diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..33d136df --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,10 @@ +## 변경사항 + +## 이슈 번호 또는 링크 + +## 리뷰 요청하기전 체크 리스트 + +- [ ] 내 코드를 스스로 리뷰해봤나요? +- [ ] 로컬 환경에서 빌드 성공했나요? +- [ ] 테스트 실시했나요? +- [ ] 테스트 코드 작성했나요? (추후에..) diff --git a/packages/react-component/src/components/Flex/Flex.tsx b/packages/react-component/src/components/Flex/Flex.tsx new file mode 100644 index 00000000..1a7767fe --- /dev/null +++ b/packages/react-component/src/components/Flex/Flex.tsx @@ -0,0 +1,140 @@ +import { HTMLAttributes, forwardRef, memo, useMemo } from 'react' + +import { useTheme } from '@emotion/react' + +import { Box } from 'src/elements' +import { Size } from 'src/types' + +enum AlignItems { + Start = 'flex-start', + Center = 'center', + End = 'flex-end', + Baseline = 'baseline', + Stretch = 'stretch', +} + +enum JustifyContent { + Start = 'flex-start', + Center = 'center', + End = 'flex-end', + Between = 'space-between', +} + +type FlexDirectionType = 'row' | 'row-reverse' | 'column' | 'column-reverse' + +type JustifyContentType = 'start' | 'center' | 'end' | 'between' + +type AlignItemsType = 'start' | 'center' | 'end' | 'baseline' | 'stretch' + +interface FlexProps extends HTMLAttributes { + /** + * Flex Item 간의 간격 + */ + spacing?: Size | number + /** + * Flex Item 간의 간격 + */ + rowSpacing?: Size | number + /** + * Flex Item 간의 간격 + */ + colSpacing?: Size | number + /** + * Flex 컨테이너의 축 변경 + */ + direction?: FlexDirectionType + /** + * Flex 컨테이너의 축에 방향에 따라 아이템과의 정렬 방식 + */ + justify?: JustifyContentType + /** + * Flex 컨테이너의 축에 방향에 따라 아이템과의 정렬 방식 + */ + align?: AlignItemsType +} + +/** + * CSS Flex를 사용할 때, 사용하는 박스입니다. + */ +export const Flex = memo( + forwardRef( + ({ spacing, rowSpacing, colSpacing, direction = 'row', justify, align, ...rest }, ref) => { + const theme = useTheme() + + const gap = useMemo(() => { + if (spacing) { + if (typeof spacing === 'number') { + return spacing + } + return theme.spacing[spacing] + } + }, [spacing]) + + const rowGap = useMemo(() => { + if (rowSpacing) { + if (typeof rowSpacing === 'number') { + return rowSpacing + } + return theme.spacing[rowSpacing] + } + }, [rowSpacing]) + + const columnGap = useMemo(() => { + if (colSpacing) { + if (typeof colSpacing === 'number') { + return colSpacing + } + return theme.spacing[colSpacing] + } + }, [colSpacing]) + + const alignItems = useMemo(() => { + switch (align) { + case 'start': + return AlignItems.Start + case 'center': + return AlignItems.Center + case 'end': + return AlignItems.End + case 'baseline': + return AlignItems.Baseline + case 'stretch': + return AlignItems.Stretch + default: + } + }, [align]) + + const justifyContent = useMemo(() => { + switch (justify) { + case 'start': + return JustifyContent.Start + case 'center': + return JustifyContent.Center + case 'end': + return JustifyContent.End + case 'between': + return JustifyContent.Between + default: + } + }, [justify]) + + return ( + + ) + }, + ), +) + +Flex.displayName = 'Flex' diff --git a/packages/react-component/src/components/Flex/index.ts b/packages/react-component/src/components/Flex/index.ts new file mode 100644 index 00000000..12459d82 --- /dev/null +++ b/packages/react-component/src/components/Flex/index.ts @@ -0,0 +1 @@ +export * from './Flex' diff --git a/packages/react-component/src/components/Table/components/TableBody.tsx b/packages/react-component/src/components/Table/components/TableBody.tsx index 87d012cd..ad6b5420 100644 --- a/packages/react-component/src/components/Table/components/TableBody.tsx +++ b/packages/react-component/src/components/Table/components/TableBody.tsx @@ -96,7 +96,7 @@ export function TableBody({ css={[ { backgroundColor: theme.colors.white.main, - borderBottom: `1px solid ${theme.colors.white.lighter}`, + borderBottom: `1px solid ${theme.colors.gray.lighter}`, color: theme.colors.black.dark, '&:last-of-type': { borderBottom: 'none', @@ -105,7 +105,7 @@ export function TableBody({ onRowClick && { '&:hover': { cursor: 'pointer', - backgroundColor: theme.colors.white.darker, + backgroundColor: theme.colors.blue.lighter, }, }, ]} diff --git a/packages/react-component/src/components/TextInput/TextInput.tsx b/packages/react-component/src/components/TextInput/TextInput.tsx index 722190eb..64d0dae8 100644 --- a/packages/react-component/src/components/TextInput/TextInput.tsx +++ b/packages/react-component/src/components/TextInput/TextInput.tsx @@ -22,119 +22,71 @@ import { handleRegExpText, InputType, RulesType } from './helpers' export interface TextInputProps extends Omit, 'type' | 'size'> { /** - * @optional - * @type {string} * @default text * - * 'text' | 'password' - * - * @description - * Input의 타입을 정합니다 'password'가 입력되면, endAdornment가 활성화됩니다 + * 입력 필드의 타입을 정합니다 'password'가 입력되면, Password Eye가 활성화됩니다 */ type?: InputType /** - * @optional - * @type {string} * @default md * - * 'sm' | 'md' | 'lg' - * - * @description - * Input 구성요소들의 사이즈입니다 + * 입력 필드 구성요소들의 사이즈입니다 */ size?: Size /** - * @optional - * - * @description - * Input 위에 표시될 라벨입니다 + * 입력 필드 위에 표시될 라벨입니다 */ label?: string /** - * @optional - * @returns JSX.Element - * - * @description - * Input 시작지점 아이콘 버튼입니다 + * 입력 필드 시작지점 아이콘입니다. */ startAdornment?: ReactNode | ((props: SVGProps) => JSX.Element) /** - * @optional - * @returns JSX.Element - * - * @description - * Input 종료지점 아이콘 버튼입니다 + * 입력 필드 종료지점 아이콘입니다. */ endAdornment?: ReactNode | ((props: SVGProps) => JSX.Element) /** - * @optional - * @type {boolean} - * - * false이면, borderColor에 'red'가 적용됩니다 - * || true이면, borderColor에 'gray'가 적용됩니다 + * 1. 값이 false이면, borderColor에 'gray'가 적용됩니다 + * 2. 값이 true이면, borderColor에 'red'가 적용됩니다 * - * @description - * 에러 발생시 borderColor를 불린 값에 따라 변경합니다 + * error의 불린 값에 따라 입력 필드의 borderColor와 helperText의 텍스트 컬러를 제어합니다. */ error?: boolean /** - * @optional * - * @description - * Input 밑에 나타나는 도움 글입니다 - * @description - * default color는 'green'이며, error props의 값이 true이면, 'red'가 적용됩니다 + * 1. error Props의 값이 false이면, 텍스트와 아이콘의 컬러가 'green'으로 적용됩니다. + * 2. error props의 값이 true이면, 텍스트와 아이콘의 컬러가 'red'로 적용됩니다. + * + * 입력 필드 밑에 나타나는 도움 글입니다 error와 같이 사용 됩니다. */ helperText?: string /** - * @optional - * @type {boolean} - * false이면, 사용하지 않습니다 - * || true이면, label 옆에 *가 표시됩니다 * - * @description - * Input의 label에 표시될 *의 사용여부입니다 + * 1. 값을 입력하지 않으면, *가 표시되지 않습니다. + * 2. true이면, label 옆에 *가 표시됩니다 + * + * 입력 필드의 label에 표시될 *의 사용여부입니다 */ withAsterisk?: boolean /** - * @optional - * @type {string} - * - * @value - * 'onlyDigit' | 'onlyDigitAndDash' | 'onlyDigitAndDot' | 'onlyDigitAndDotDash' - * | 'onlyEnglish' | 'onlyEnglishAndDash' | 'onlyEnglishAndDot' | 'onlyEnglishAndDotDash' - * | 'onlyEnglishAndDigit' - * - * @description * 입력하는 값을 rules에 따라 제한합니다 */ rules?: RulesType /** + * @default + * false + * + * 1. 값이 false이면, 텍스트의 양 사이드에 비어있는 텍스트 값이 제거됩니다. + * 2. 값이 true이면, 텍스트의 양 사이드에 비어있는 텍스트 값이 제거되지 않습니다. + * * value에 trim() 처리 여부입니다. */ disabledTrim?: boolean } /** - * @param InputHTMLAttributes(optional) - * @param type(optional) Input의 타입을 정합니다 'password'가 입력되면, endAdornment가 활성화됩니다 - * @param size(optional) Input 구성요소들의 사이즈입니다 - * @param label(optional) Input 위에 표시될 라벨입니다 - * @param startAdornment(optional) Input 시작지점 아이콘 버튼입니다 - * @param endAdornment(optional) Input 종료지점 아이콘 버튼입니다 - * @param error(optional) 에러 발생시 borderColor를 불린 값에 따라 변경합니다 - * @param helperText(optional) default color는 'green'이며, error props의 값이 true이면, 'red'가 적용됩니다 - * @param required(optional) Input의 label에 표시될 *의 사용여부입니다 - * @param rules(optional) Input에 입력하는 값을 rules에 따라 제한합니다 - * @example - * + * https://www.developers.musma.net/docs/react-components/textinput * - * @description * Text를 입력할 수 있는 Input입니다 */ export const TextInput = forwardRef( diff --git a/packages/react-component/src/components/Typography/Typography.tsx b/packages/react-component/src/components/Typography/Typography.tsx index 25705868..15332f32 100644 --- a/packages/react-component/src/components/Typography/Typography.tsx +++ b/packages/react-component/src/components/Typography/Typography.tsx @@ -13,43 +13,35 @@ import { export type TypographyProps = { /** - * @optional - * @type {string} * @default body1 * - * h1 | h2 | h3 | h4 | h5 | h6 - * body1 | body2 | body3 - * cation1 | cation2 - * subTitle1 | subTitle2 | subTitle3 - * - * @description * 표시될 문자의 타입을 정합니다 */ type?: HeadingType | BodyType | CaptionType | SubTitleType /** - * @description + * + */ + color?: string + /** * CSS Prop입니다 */ className?: string } /** + * https://www.developers.musma.net/docs/react-components/typography * - * @param type(optional) h1 | h2 | h3 | h4 | h5 | h6 | body1 | body2 | body3 | cation1 | cation2 | subTitle1 | subTitle2 | subTitle3 - * @param className(optional) CSS Prop입니다 - * @param children(required) 표시할 문자입니다 - * @example - * - * example - * - * - * @description * 특정 액션이 포함되지 않은 문장이나 문자를 표시할 때 사용합니다 */ -export const Typography = ({ type, className, children }: PropsWithChildren) => { +export const Typography = ({ + type, + color, + className, + children, +}: PropsWithChildren) => { if (type === 'body1' || type === 'body2' || type === 'body3') { return ( - + {children} ) @@ -57,7 +49,7 @@ export const Typography = ({ type, className, children }: PropsWithChildren + {children} ) @@ -72,7 +64,7 @@ export const Typography = ({ type, className, children }: PropsWithChildren + {children} ) @@ -80,14 +72,14 @@ export const Typography = ({ type, className, children }: PropsWithChildren + {children} ) } return ( - + {children} ) diff --git a/packages/react-component/src/components/Typography/components/Body.tsx b/packages/react-component/src/components/Typography/components/Body.tsx index ae30d72d..9354d164 100644 --- a/packages/react-component/src/components/Typography/components/Body.tsx +++ b/packages/react-component/src/components/Typography/components/Body.tsx @@ -5,10 +5,16 @@ export type BodyType = 'body1' | 'body2' | 'body3' export interface BodyProps { type?: 'body' variant?: BodyType + color?: string className?: string } -export const Body = ({ variant = 'body1', children, className }: PropsWithChildren) => { +export const Body = ({ + variant = 'body1', + color, + children, + className, +}: PropsWithChildren) => { return (

) => { @@ -20,6 +22,7 @@ export const Caption = ({ margin: 0, fontWeight: 400, lineHeight: 1, + color, }, { caption1: { diff --git a/packages/react-component/src/components/Typography/components/Heading.tsx b/packages/react-component/src/components/Typography/components/Heading.tsx index c78e96d1..6dd61972 100644 --- a/packages/react-component/src/components/Typography/components/Heading.tsx +++ b/packages/react-component/src/components/Typography/components/Heading.tsx @@ -7,11 +7,13 @@ export type HeadingType = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' export interface HeadingProps { type?: 'heading' variant?: HeadingType + color?: string className?: string } export const Heading = ({ variant = 'h1', + color, children, className, }: PropsWithChildren) => { @@ -22,6 +24,7 @@ export const Heading = ({ { margin: 0, lineHeight: 1, + color, }, { h1: { fontSize: '2.5rem', fontWeight: 700, letterSpacing: -0.6 }, diff --git a/packages/react-component/src/components/Typography/components/SubTitle.tsx b/packages/react-component/src/components/Typography/components/SubTitle.tsx index cffedc07..2a81323c 100644 --- a/packages/react-component/src/components/Typography/components/SubTitle.tsx +++ b/packages/react-component/src/components/Typography/components/SubTitle.tsx @@ -5,11 +5,13 @@ export type SubTitleType = 'subTitle1' | 'subTitle2' | 'subTitle3' export type SubTitleProps = { type?: 'subTitle' variant?: SubTitleType + color?: string className?: string } export const SubTitle = ({ variant = 'subTitle1', + color, children, className, }: PropsWithChildren) => { @@ -19,6 +21,7 @@ export const SubTitle = ({ { margin: 0, lineHeight: 1, + color, }, { subTitle1: { diff --git a/packages/react-component/src/components/index.ts b/packages/react-component/src/components/index.ts index 5169c61b..9c456b7f 100644 --- a/packages/react-component/src/components/index.ts +++ b/packages/react-component/src/components/index.ts @@ -12,6 +12,7 @@ export * from './DateRangePicker' export * from './Divider' export * from './Drawer' export * from './Dropdown' +export * from './Flex' export * from './Grid' export * from './Header' export * from './IconAdornment' diff --git a/packages/react-component/src/theme/MusmaProvider/DefaultTheme.ts b/packages/react-component/src/theme/MusmaProvider/DefaultTheme.ts index c5e0c78a..2c2324b1 100644 --- a/packages/react-component/src/theme/MusmaProvider/DefaultTheme.ts +++ b/packages/react-component/src/theme/MusmaProvider/DefaultTheme.ts @@ -23,13 +23,13 @@ const DefaultTheme: MusmaTheme = { light: '#118EE5', main: '#036DB7', dark: '#025996', - darker: '#01677D', + darker: '#003E6A', }, blue: { - lighter: '#1FA2FF', - light: '#006CE8', - main: '#084C9C', - dark: '#013F6B', + lighter: '#F2F8FB', + light: '#118EE5', + main: '#036DB7', + dark: '#025996', darker: '#003E6A', }, black: { @@ -54,25 +54,25 @@ const DefaultTheme: MusmaTheme = { darker: '#EAEAEA', }, red: { - lighter: '#FF774E', - light: '#FF440D', - main: '#E82717', - dark: '#9C1408', - darker: '#7A252C', + lighter: '#EDDDDD', + light: '#FF4D4F', + main: '#CA3C3D', + dark: '#A63132', + darker: '#940E0F', }, green: { - lighter: '#69C7C6', - light: '#1BB500', - main: '#009C45', - dark: '#00823B', - darker: '#004F24', + lighter: '#E6E8D8', + light: '#00AA52', + main: '#A63132', + dark: '#066B36', + darker: '#054522', }, orange: { - lighter: '#FFBD4C', - light: '#FA9F00', - main: '#F5630C', - dark: '#DB570B', - darker: '#C24D0A', + lighter: '#FD9009', + light: '#FFAB43', + main: '#FD9009', + dark: '#E76F00', + darker: '#D86900', }, transparent: 'transparent', },