From fcfab6cae999dd2a4ca0ba65182b0f00e4cbf4d0 Mon Sep 17 00:00:00 2001 From: steven-yn Date: Tue, 28 Nov 2023 23:23:21 +0900 Subject: [PATCH] =?UTF-8?q?add:=20=EA=B3=B5=EC=9A=A9=20=EC=95=84=EC=9D=B4?= =?UTF-8?q?=EC=BD=98=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/storybook/IconBoard.tsx | 68 ++++++++++++++++--- src/composable/Icon/CommonIcon.tsx | 11 +++ src/composable/Icon/Icon.test.tsx | 31 ++++++++- src/composable/Icon/SocialIcon.tsx | 18 ++--- src/mock/iconTokens.mock.ts | 9 +++ src/types/designToken.d.ts | 10 ++- src/types/props/Icon.d.ts | 15 ++++ src/utils/string/iconAssetEndpoint.ts | 7 ++ ...rmat.ts => socialIconResourceSrcFormat.ts} | 6 +- src/utils/string/string.test.ts | 8 +-- 10 files changed, 151 insertions(+), 32 deletions(-) create mode 100644 src/composable/Icon/CommonIcon.tsx create mode 100644 src/types/props/Icon.d.ts create mode 100644 src/utils/string/iconAssetEndpoint.ts rename src/utils/string/{iconResourceSrcFormat.ts => socialIconResourceSrcFormat.ts} (76%) diff --git a/src/components/storybook/IconBoard.tsx b/src/components/storybook/IconBoard.tsx index 281a828..b91abc8 100644 --- a/src/components/storybook/IconBoard.tsx +++ b/src/components/storybook/IconBoard.tsx @@ -1,11 +1,23 @@ import React from 'react'; import Grid from '@/composable/Grid/Grid'; +import CommonIcon from '@/composable/Icon/CommonIcon'; import SocialIcon from '@/composable/Icon/SocialIcon'; import Text from '@/composable/Text/Text'; import { backgroundColorVariants } from '@/styles/color.css'; import { globalThemeVars } from '@/styles/theme.css'; const IconBoard = () => { + const gridStyle = { + width: 'fit-content', + justifyItems: 'center', + alignItems: 'center', + rowGap: '1rem', + columnGap: '2rem', + margin: '1rem 0', + padding: '1.5rem', + borderRadius: '1rem', + }; + return ( <> { color: globalThemeVars.color['gray-scale-04'], }} > - Skill Icons + Common Icons + + + + { autoFlow="column" templateColumns="repeat(16, 2rem)" templateRows="repeat(19, 2rem)" - style={{ - width: 'fit-content', - justifyItems: 'center', - alignItems: 'center', - rowGap: '1rem', - columnGap: '2rem', - margin: '1rem 0', - padding: '1.5rem', - borderRadius: '1rem', - }} + style={gridStyle} > @@ -217,6 +229,40 @@ const Social = ({ company, format }: SocialProps) => { ); }; +interface CommonProps { + format?: 'png' | 'svg'; +} + +const Common = ({ format }: CommonProps) => { + return ( + <> + + + + + + + + + ); +}; + IconBoard.Social = Social; +IconBoard.Common = Common; export default IconBoard; diff --git a/src/composable/Icon/CommonIcon.tsx b/src/composable/Icon/CommonIcon.tsx new file mode 100644 index 0000000..fe32fb2 --- /dev/null +++ b/src/composable/Icon/CommonIcon.tsx @@ -0,0 +1,11 @@ +import Image from 'next/image'; +import React from 'react'; +import iconAssetEndpoint from '@/utils/string/iconAssetEndpoint'; + +const CommonIcon = ({ variant, format, ...props }: CommonIconProps) => { + const path = iconAssetEndpoint(variant); + + return {variant}; +}; + +export default CommonIcon; diff --git a/src/composable/Icon/Icon.test.tsx b/src/composable/Icon/Icon.test.tsx index 7b25e0f..a4c1dfd 100644 --- a/src/composable/Icon/Icon.test.tsx +++ b/src/composable/Icon/Icon.test.tsx @@ -2,14 +2,43 @@ import { render } from '@testing-library/react'; import { iconBackgroundTokens, iconColorTokens, + iconCommonTokens, iconCompanyTokens, iconStateTokens, } from '@/mock/iconTokens.mock'; import { randomIndex, randomBetweenNumber } from '@/utils/number/random'; import capitalizeFirstLetter from '@/utils/string/capitalizeFirstLetter'; +import CommonIcon from './CommonIcon'; import SocialIcon from './SocialIcon'; -describe('Icon 컴포넌트', () => { +describe('Icon 컴포넌트들', () => { + describe('1. CommonIcon 컴포넌트들', () => { + test('1. Image 컴포넌트가 정확한 props로 렌더링 되는가?', () => { + const testProps = { + variant: iconCommonTokens[randomIndex(iconCommonTokens)], + size: randomBetweenNumber(0, 200), + }; + + const { getByRole } = render( + , + ); + const image = getByRole('img'); + + expect(image).toHaveAttribute('width', testProps.size.toString()); + expect(image).toHaveAttribute('height', testProps.size.toString()); + expect(image).toHaveAttribute('alt', testProps.variant); + + expect(image).toHaveAttribute( + 'src', + expect.stringContaining(`${testProps.variant.toLowerCase()}`), + ); + }); + }); + test('1. Image 컴포넌트가 정확한 props로 렌더링 되는가?', () => { const testProps = { company: iconCompanyTokens[randomIndex(iconCompanyTokens)], diff --git a/src/composable/Icon/SocialIcon.tsx b/src/composable/Icon/SocialIcon.tsx index 6db560a..858ceba 100644 --- a/src/composable/Icon/SocialIcon.tsx +++ b/src/composable/Icon/SocialIcon.tsx @@ -1,12 +1,6 @@ -import Image, { ImageProps } from 'next/image'; -import { ASSET_ENDPOINT } from '@/const/endpoint'; -import iconResourceSrcFormat from '@/utils/string/iconResourceSrcFormat'; - -type ModifiedImageProps = Omit; -type SocialProps = ODSIconTokenInterface & - ModifiedImageProps & { - format?: 'png' | 'svg'; - }; +import Image from 'next/image'; +import iconAssetEndpoint from '@/utils/string/iconAssetEndpoint'; +import socialIconResourceSrcFormat from '@/utils/string/socialIconResourceSrcFormat'; const SocialIcon = ({ company, @@ -15,15 +9,15 @@ const SocialIcon = ({ state, format, ...props -}: SocialProps) => { - const resource = iconResourceSrcFormat({ +}: SocialIconProps) => { + const resource = socialIconResourceSrcFormat({ company, color, background, state, }); - const path = `${ASSET_ENDPOINT}/icons/${company.toLowerCase()}`; + const path = iconAssetEndpoint(company); return ( ; + type IconProps = ModifiedImageProps & { + format?: 'png' | 'svg'; + }; + type CommonIconProps = IconProps & { + variant: CommonIconToken; + }; + type SocialIconProps = ODSIconTokenInterface & + IconProps & { + company: CompanyIconToken; + }; +} diff --git a/src/utils/string/iconAssetEndpoint.ts b/src/utils/string/iconAssetEndpoint.ts new file mode 100644 index 0000000..832ec77 --- /dev/null +++ b/src/utils/string/iconAssetEndpoint.ts @@ -0,0 +1,7 @@ +import { ASSET_ENDPOINT } from '@/const/endpoint'; + +const iconAssetEndpoint = (iconName: string) => { + return `${ASSET_ENDPOINT}/icons/${iconName.toLowerCase()}`; +}; + +export default iconAssetEndpoint; diff --git a/src/utils/string/iconResourceSrcFormat.ts b/src/utils/string/socialIconResourceSrcFormat.ts similarity index 76% rename from src/utils/string/iconResourceSrcFormat.ts rename to src/utils/string/socialIconResourceSrcFormat.ts index 1fa851c..66f0f78 100644 --- a/src/utils/string/iconResourceSrcFormat.ts +++ b/src/utils/string/socialIconResourceSrcFormat.ts @@ -1,11 +1,11 @@ import capitalizeFirstLetter from './capitalizeFirstLetter'; -const iconResourceSrcFormat = ({ +const socialIconResourceSrcFormat = ({ company, color, background, state, -}: ODSIconTokenInterface) => { +}: SocialIconProps) => { return encodeURIComponent( `Company=${capitalizeFirstLetter(company)}, Color=${capitalizeFirstLetter( color, @@ -15,4 +15,4 @@ const iconResourceSrcFormat = ({ ); }; -export default iconResourceSrcFormat; +export default socialIconResourceSrcFormat; diff --git a/src/utils/string/string.test.ts b/src/utils/string/string.test.ts index 47da6ba..a144acc 100644 --- a/src/utils/string/string.test.ts +++ b/src/utils/string/string.test.ts @@ -1,6 +1,6 @@ import capitalizeFirstLetter from './capitalizeFirstLetter'; -import iconResourceSrcFormat from './iconResourceSrcFormat'; import replaceAll from './replaceAll'; +import socialIconResourceSrcFormat from './socialIconResourceSrcFormat'; describe('string', () => { describe('capitalizeFirstLetter', () => { @@ -103,9 +103,9 @@ describe('string', () => { }); }); - describe('iconResourceSrcFormat', () => { + describe('socialIconResourceSrcFormat', () => { it('should format the icon resource source correctly', () => { - const mockIconToken: ODSIconTokenInterface = { + const mockIconToken: SocialIconProps = { company: 'GOOGLE', color: 'BRAND', background: 'CIRCULAR', @@ -116,7 +116,7 @@ describe('string', () => { 'Company=Google, Color=Brand, Background=Circular, State=Hover', ); - const result = iconResourceSrcFormat(mockIconToken); + const result = socialIconResourceSrcFormat(mockIconToken); expect(result).toBe(expectedOutput); });