diff --git a/packages/design-system/src/components/button/Button.stories.tsx b/packages/design-system/src/components/button/Button.stories.tsx index fa7c70dc..e76d2169 100644 --- a/packages/design-system/src/components/button/Button.stories.tsx +++ b/packages/design-system/src/components/button/Button.stories.tsx @@ -1,18 +1,108 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import Button from './Button'; -// Storybook에 컴포넌트를 어떻게 표시할지 정의합니다. const meta: Meta = { - title: 'UI/Button', + title: 'Components/Button', component: Button, tags: ['autodocs'], + parameters: { + layout: 'centered', + docs: { + description: { + component: + '**애플리케이션 전반에서 사용될 기본 버튼입니다.** `variant`로 주/보조 스타일을, `size`로 크기를, `isDisabled`로 비활성화 상태를 제어합니다.', + }, + }, + }, + argTypes: { + variant: { + control: 'inline-radio', + options: ['primary', 'secondary'], + }, + size: { + control: 'select', + options: ['small', 'medium', 'large'], + }, + isDisabled: { + control: 'boolean', + }, + children: { + control: 'text', + }, + onClick: { + action: 'clicked', + description: '버튼 클릭 시 호출되는 이벤트 핸들러입니다.', + }, + className: { table: { disable: true } }, + }, + + args: { + variant: 'primary', + size: 'medium', + isDisabled: false, + children: 'Button', + }, }; export default meta; + type Story = StoryObj; export const Primary: Story = { + name: 'variant: primary', args: { + variant: 'primary', children: 'Primary Button', }, }; + +export const Secondary: Story = { + name: 'variant: secondary', + args: { + variant: 'secondary', + children: 'Secondary Button', + }, +}; + +export const Large: Story = { + name: 'size: large', + args: { + size: 'large', + children: 'Large Button', + }, +}; + +export const Small: Story = { + name: 'size: small', + args: { + size: 'small', + children: 'Small Button', + }, +}; + +export const Disabled: Story = { + name: 'state: disabled', + args: { + isDisabled: true, + }, + render: (args) => ( +
+ + +
+ ), +}; + +export const WithAlertOnClick: Story = { + name: 'onClick with Alert', + args: { + children: 'onClick test', + onClick: () => { + alert('버튼이 클릭되었습니다.'); + }, + }, +}; diff --git a/packages/design-system/src/components/button/Button.tsx b/packages/design-system/src/components/button/Button.tsx index 7db19522..cda7e826 100644 --- a/packages/design-system/src/components/button/Button.tsx +++ b/packages/design-system/src/components/button/Button.tsx @@ -1,10 +1,50 @@ +import { cn } from '@/lib'; +import { cva } from 'class-variance-authority'; + interface ButtonProps extends React.ButtonHTMLAttributes { - children: React.ReactNode; + variant?: 'primary' | 'secondary'; + size?: 'small' | 'medium' | 'large'; + isDisabled?: boolean; } -const Button = ({ children, ...props }: ButtonProps) => { +const buttonVariants = cva( + 'cursor-pointer rounded-[0.4rem] disabled:cursor-not-allowed w-full', + { + variants: { + variant: { + primary: + 'bg-gray900 text-white-bg hover:bg-gray800 active:bg-gray900 disabled:bg-gray200 disabled:text-font-ltgray-4', + secondary: + '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', + }, + size: { + small: 'px-[1.2rem] py-[0.8rem] sub5-sb', + medium: 'px-[1.2rem] py-[1.2rem] sub5-sb', + large: 'px-[1.6rem] py-[1.5rem] sub3-sb', + }, + }, + defaultVariants: { + variant: 'primary', + size: 'medium', + }, + } +); + +const Button = ({ + variant = 'primary', + size, + children, + className, + isDisabled = false, + ...props +}: ButtonProps) => { return ( - );