Skip to content

Commit 4be9fd5

Browse files
Feat(design-system): Button 컴포넌트 구현 (#32)
* feat: button 공통 컴포넌트 구현 * feat: button story 작성 * feat: button size별로 padding 추가 * feat: large size px 수정
1 parent f8ae875 commit 4be9fd5

File tree

2 files changed

+135
-5
lines changed

2 files changed

+135
-5
lines changed
Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,108 @@
11
import type { Meta, StoryObj } from '@storybook/react-vite';
22
import Button from './Button';
33

4-
// Storybook에 컴포넌트를 어떻게 표시할지 정의합니다.
54
const meta: Meta<typeof Button> = {
6-
title: 'UI/Button',
5+
title: 'Components/Button',
76
component: Button,
87
tags: ['autodocs'],
8+
parameters: {
9+
layout: 'centered',
10+
docs: {
11+
description: {
12+
component:
13+
'**애플리케이션 전반에서 사용될 기본 버튼입니다.** `variant`로 주/보조 스타일을, `size`로 크기를, `isDisabled`로 비활성화 상태를 제어합니다.',
14+
},
15+
},
16+
},
17+
argTypes: {
18+
variant: {
19+
control: 'inline-radio',
20+
options: ['primary', 'secondary'],
21+
},
22+
size: {
23+
control: 'select',
24+
options: ['small', 'medium', 'large'],
25+
},
26+
isDisabled: {
27+
control: 'boolean',
28+
},
29+
children: {
30+
control: 'text',
31+
},
32+
onClick: {
33+
action: 'clicked',
34+
description: '버튼 클릭 시 호출되는 이벤트 핸들러입니다.',
35+
},
36+
className: { table: { disable: true } },
37+
},
38+
39+
args: {
40+
variant: 'primary',
41+
size: 'medium',
42+
isDisabled: false,
43+
children: 'Button',
44+
},
945
};
1046

1147
export default meta;
48+
1249
type Story = StoryObj<typeof Button>;
1350

1451
export const Primary: Story = {
52+
name: 'variant: primary',
1553
args: {
54+
variant: 'primary',
1655
children: 'Primary Button',
1756
},
1857
};
58+
59+
export const Secondary: Story = {
60+
name: 'variant: secondary',
61+
args: {
62+
variant: 'secondary',
63+
children: 'Secondary Button',
64+
},
65+
};
66+
67+
export const Large: Story = {
68+
name: 'size: large',
69+
args: {
70+
size: 'large',
71+
children: 'Large Button',
72+
},
73+
};
74+
75+
export const Small: Story = {
76+
name: 'size: small',
77+
args: {
78+
size: 'small',
79+
children: 'Small Button',
80+
},
81+
};
82+
83+
export const Disabled: Story = {
84+
name: 'state: disabled',
85+
args: {
86+
isDisabled: true,
87+
},
88+
render: (args) => (
89+
<div style={{ display: 'flex', gap: '16px' }}>
90+
<Button {...args} variant="primary">
91+
Primary
92+
</Button>
93+
<Button {...args} variant="secondary">
94+
Secondary
95+
</Button>
96+
</div>
97+
),
98+
};
99+
100+
export const WithAlertOnClick: Story = {
101+
name: 'onClick with Alert',
102+
args: {
103+
children: 'onClick test',
104+
onClick: () => {
105+
alert('버튼이 클릭되었습니다.');
106+
},
107+
},
108+
};

packages/design-system/src/components/button/Button.tsx

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,50 @@
1+
import { cn } from '@/lib';
2+
import { cva } from 'class-variance-authority';
3+
14
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
2-
children: React.ReactNode;
5+
variant?: 'primary' | 'secondary';
6+
size?: 'small' | 'medium' | 'large';
7+
isDisabled?: boolean;
38
}
49

5-
const Button = ({ children, ...props }: ButtonProps) => {
10+
const buttonVariants = cva(
11+
'cursor-pointer rounded-[0.4rem] disabled:cursor-not-allowed w-full',
12+
{
13+
variants: {
14+
variant: {
15+
primary:
16+
'bg-gray900 text-white-bg hover:bg-gray800 active:bg-gray900 disabled:bg-gray200 disabled:text-font-ltgray-4',
17+
secondary:
18+
'bg-white-bg text-font-black-1 hover:bg-gray200 active:bg-white-bg disabled:bg-gray200 disabled:text-font-ltgray-4 outline outline-gray200',
19+
},
20+
size: {
21+
small: 'px-[1.2rem] py-[0.8rem] sub5-sb',
22+
medium: 'px-[1.2rem] py-[1.2rem] sub5-sb',
23+
large: 'px-[1.6rem] py-[1.5rem] sub3-sb',
24+
},
25+
},
26+
defaultVariants: {
27+
variant: 'primary',
28+
size: 'medium',
29+
},
30+
}
31+
);
32+
33+
const Button = ({
34+
variant = 'primary',
35+
size,
36+
children,
37+
className,
38+
isDisabled = false,
39+
...props
40+
}: ButtonProps) => {
641
return (
7-
<button type="button" {...props}>
42+
<button
43+
type="button"
44+
className={cn(buttonVariants({ variant, size }), className)}
45+
disabled={isDisabled}
46+
{...props}
47+
>
848
{children}
949
</button>
1050
);

0 commit comments

Comments
 (0)