Skip to content

Commit

Permalink
[#364] Badge 컴포넌트 (#396)
Browse files Browse the repository at this point in the history
* feat: Badge 컴포넌트 작성

* feat: Badge 컴포넌트 Storybook 작성

* chore: heart 아이콘 fill color 수정
  • Loading branch information
hanyugeon authored and gxxrxn committed Jun 17, 2024
1 parent 55a6b98 commit 86edc76
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 2 deletions.
4 changes: 2 additions & 2 deletions public/icons/heart.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
56 changes: 56 additions & 0 deletions src/stories/Base/Badge.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import Badge from '@/ui/Base/Badge';
import { IconHeart } from '@public/icons';
import { Meta, StoryObj } from '@storybook/react';

const meta: Meta<typeof Badge> = {
title: 'Base/Badge',
component: Badge,
tags: ['autodocs'],
};

export default meta;

type Story = StoryObj<typeof Badge>;

export const Default: Story = {
args: {
size: 'small',
colorScheme: 'main-light',
fontWeight: 'bold',
},
render: args => <Badge {...args}>프론트엔드 개발자</Badge>,
};

export const BookshelfLike: Story = {
args: {
size: 'small',
colorScheme: 'red',
fontWeight: 'bold',
},
render: args => (
<Badge {...args}>
<div className="h-[1.3rem] w-[1.3rem] fill-white">
<IconHeart />
</div>
99
</Badge>
),
};

export const GroupProgress: Story = {
args: {
size: 'large',
colorScheme: 'main',
fontWeight: 'bold',
},
render: args => <Badge {...args}>진행중</Badge>,
};

export const GroupDisclosure: Story = {
args: {
size: 'medium',
colorScheme: 'grey',
fontWeight: 'normal',
},
render: args => <Badge {...args}>공개</Badge>,
};
93 changes: 93 additions & 0 deletions src/ui/Base/Badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { PropsWithChildren, useMemo } from 'react';

type Size = 'small' | 'medium' | 'large';
type ColorScheme = 'main' | 'main-light' | 'grey' | 'red';
type FontWeight = 'thin' | 'normal' | 'bold';

type BadgeProps = PropsWithChildren<{
size?: Size;
colorScheme?: ColorScheme;
fontWeight?: FontWeight;
isFilled?: boolean;
}>;

const getSizeClasses = (size: Size) => {
switch (size) {
case 'small': {
return 'h-[1.8rem] text-2xs';
}
case 'medium': {
return 'h-[1.9rem] text-xs';
}
case 'large': {
return 'h-[2.1rem] text-xs';
}
}
};

const getSchemeClasses = (colorScheme: ColorScheme, isFilled: boolean) => {
switch (colorScheme) {
case 'main': {
return isFilled
? 'border-main-900 bg-main-900 text-white'
: 'border-main-900 text-main-900';
}
case 'main-light': {
return isFilled
? 'border-main-600 bg-main-600 text-white'
: 'border-main-600 text-main-600';
}
case 'grey': {
return isFilled
? 'border-black-100 bg-black-100 text-black-500'
: 'border-black-500 text-black-500';
}
case 'red': {
return isFilled
? 'border-warning-800 bg-warning-800 text-white'
: 'border-warning-800 text-warning-800';
}
}
};

const getFontWeightClasses = (fontWeight: FontWeight) => {
switch (fontWeight) {
case 'thin': {
return 'font-thin';
}
case 'normal': {
return 'font-normal';
}
case 'bold': {
return 'font-bold';
}
}
};

const Badge = ({
size = 'medium',
colorScheme = 'main',
fontWeight = 'normal',
isFilled = true,
children,
...props
}: BadgeProps) => {
const computedClasses = useMemo(() => {
const sizeClass = getSizeClasses(size);
const schemeClass = getSchemeClasses(colorScheme, isFilled);
const fontWeightClass = getFontWeightClasses(fontWeight);

return [sizeClass, schemeClass, fontWeightClass].join(' ');
}, [size, colorScheme, isFilled, fontWeight]);

return (
<div
className={`m-0 flex w-fit items-center justify-center gap-[0.4rem] rounded-[0.5rem] border-[0.05rem] px-[0.8rem] py-[0.25rem] ${computedClasses}`}
{...props}
>
{children}
</div>
);
};

export default Badge;

0 comments on commit 86edc76

Please sign in to comment.