Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ module.exports = {
'@emotion/styled': setRootPath('node_modules/@emotion/styled'),
};

const fileLoaderRule = config.module.rules.find((rule) => rule.test && rule.test.test('.svg'));
fileLoaderRule.exclude = /\.svg$/;

config.module.rules.push({
test: /\.svg$/,
enforce: 'pre',
loader: require.resolve('@svgr/webpack'),
});

return config;
},
};
13 changes: 11 additions & 2 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
}
webpack(config) {
config.module.rules.push({
test: /\.svg$/i,
issuer: /\.[jt]sx?$/,
use: ['@svgr/webpack'],
});

module.exports = nextConfig
return config;
},
};

module.exports = nextConfig;
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"dependencies": {
"@emotion/react": "^11.8.2",
"@emotion/styled": "^11.8.1",
"@svgr/webpack": "^5.5.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

svgr로 svg를 컴포넌트화 했을 때의 장점이 궁금합니다!

"@reduxjs/toolkit": "^1.8.0",
"@types/react-redux": "^7.1.23",
"@types/yup": "^0.29.13",
Expand Down
7 changes: 7 additions & 0 deletions src/assets/icons/dairyFree.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions src/assets/icons/lactoOvo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
84 changes: 84 additions & 0 deletions src/components/Badge/Badge.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { ComponentMeta, ComponentStory } from '@storybook/react';
import { Badge } from './Badge';

export default {
title: 'Badge',
component: Badge,
args: {
size: 'small',
},
} as ComponentMeta<typeof Badge>;

const Template: ComponentStory<typeof Badge> = (args) => <Badge {...args} />;

export const dairyFree = Template.bind({});

dairyFree.args = {
iconType: 'dairyFree',
};

export const lactoOvo = Template.bind({});

lactoOvo.args = {
iconType: 'lactoOvo',
};

export const lactoOvoVegetarian = Template.bind({});

lactoOvoVegetarian.args = {
iconType: 'lactoOvoVegetarian',
};

export const vegetarian = Template.bind({});

vegetarian.args = {
iconType: 'vegetarian',
};

export const vegan = Template.bind({});

vegan.args = {
iconType: 'vegan',
};

export const glutenFree = Template.bind({});

glutenFree.args = {
iconType: 'glutenFree',
};

export const popular = Template.bind({});

popular.args = {
iconType: 'popular',
};

export const paleolithic = Template.bind({});

paleolithic.args = {
iconType: 'paleolithic',
};

export const paleo = Template.bind({});

paleo.args = {
iconType: 'paleo',
};

export const primal = Template.bind({});

primal.args = {
iconType: 'primal',
};

export const healthy = Template.bind({});

healthy.args = {
iconType: 'healthy',
};

export const pescatarian = Template.bind({});

pescatarian.args = {
iconType: 'pescatarian',
};
30 changes: 30 additions & 0 deletions src/components/Badge/Badge.styled.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import styled from '@emotion/styled';
import LactoOvo from 'assets/icons/lactoOvo.svg';
import { StyledBadgeProps } from './Badge.types';

const sizes = {
small: {
fontSize: '14px',
},
large: {
fontSize: '16px',
},
};

export const StyledBadge = styled.div<StyledBadgeProps>`
display: inline-flex;
align-items: center;
justify-content: center;
gap: 10px;
border-radius: 30px;
padding: 1em;
color: ${({ theme }) => theme.color.white};
background-color: ${({ $color, theme }) => theme.color[$color]};
max-height: 2.5em;
text-transform: uppercase;
font-size: ${({ $size }) => sizes[$size].fontSize};
`;

export const StyledLactoOvo = styled(LactoOvo)`
font-size: 20px;
`;
78 changes: 78 additions & 0 deletions src/components/Badge/Badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import DairyFree from 'assets/icons/dairyFree.svg';
import { FaLeaf, FaFish } from 'react-icons/fa';
import { GiThreeLeaves, GiGrain, GiMeat, GiMuscleUp } from 'react-icons/gi';
import { BsStars } from 'react-icons/bs';
import { StyledBadge, StyledLactoOvo } from './Badge.styled';
import { BadgeProps, BadgeInfos } from './Badge.types';

const BADGE: BadgeInfos = {
dairyFree: {
icon: <DairyFree />,
text: 'dairy-free',
color: 'badgePurple',
},
lactoOvo: {
icon: <StyledLactoOvo />,
text: 'lacto-ovo',
color: 'badgePurple',
},
lactoOvoVegetarian: {
icon: <StyledLactoOvo />,
text: 'lacto-ovo',
color: 'badgePurple',
},
vegetarian: {
icon: <FaLeaf />,
text: 'vegetarian',
color: 'badgeGreen',
},
vegan: {
icon: <GiThreeLeaves />,
text: 'vegan',
color: 'badgeGreen',
},
glutenFree: {
icon: <GiGrain />,
text: 'gluten-free',
color: 'badgePink',
},
popular: {
icon: <BsStars />,
text: 'popular',
color: 'badgePink',
},
paleolithic: {
icon: <GiMeat />,
text: 'paleo',
color: 'badgePink',
},
paleo: {
icon: <GiMeat />,
text: 'paleo',
color: 'badgePink',
},
primal: {
icon: <GiMeat />,
text: 'primal',
color: 'badgePink',
},
healthy: {
icon: <GiMuscleUp />,
text: 'healthy',
color: 'badgeNavy',
},
pescatarian: {
icon: <FaFish />,
text: 'pescatarian',
color: 'badgeNavy',
},
};

export const Badge = ({ iconType, size }: BadgeProps) => {
return (
<StyledBadge $color={BADGE[iconType].color} $size={size}>
{BADGE[iconType].icon}
<span>{BADGE[iconType].text}</span>
</StyledBadge>
);
};
49 changes: 49 additions & 0 deletions src/components/Badge/Badge.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
type IconType =
| 'dairyFree'
| 'lactoOvo'
| 'lactoOvoVegetarian'
| 'vegetarian'
| 'vegan'
| 'glutenFree'
| 'popular'
| 'paleolithic'
| 'paleo'
| 'primal'
| 'healthy'
| 'pescatarian';

type Size = 'small' | 'large';

type Text =
| 'dairy-free'
| 'lacto-ovo'
| 'lacto-ovo'
| 'vegetarian'
| 'vegan'
| 'gluten-free'
| 'popular'
| 'paleo'
| 'paleo'
| 'primal'
| 'healthy'
| 'pescatarian';

type Color = 'badgePink' | 'badgePurple' | 'badgeGreen' | 'badgeNavy';

export interface BadgeProps {
iconType: IconType;
size: Size;
}

export interface StyledBadgeProps {
$color: Color;
$size: Size;
}

export type BadgeInfos = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호 반복되는 타입의 객체를 이런 식으로 정의하는 방법이 있네요 굿굿

[key in IconType]: {
icon: JSX.Element;
text: Text;
color: Color;
};
};
Loading