Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 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
2 changes: 2 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ module.exports = {
'filenames', // 파일이름 강제
],
rules: {
//@storybook/react 빨간줄 오류 삭제
'storybook/no-renderer-packages': 'off',
// 절대경로 사용
'no-relative-import-paths/no-relative-import-paths': [
'error',
Expand Down
52 changes: 52 additions & 0 deletions src/components/ui/button/button.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import type { Meta, StoryObj } from '@storybook/react';
Copy link
Contributor

Choose a reason for hiding this comment

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

기본으로 설치된 스토리북 패키지가 nextjs인데 react 여서 아마 lint 에서 오류가 난것 같습니다!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

네 맞아요 ㅜ 빨간줄로 안떠서 확인을 차마 못했네요

Copy link
Contributor

Choose a reason for hiding this comment

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

아마 린트에서 패키지 다른거 오류잡는거 off 해놓아서 그런것 같습니다 ~!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

맞습니다 제가 .eslintrc.js 에서 'storybook/no-renderer-packages': 'off', 이거 설정 해놨었습니다..

import Link from 'next/link';
import Button from './button';

const meta: Meta<typeof Button> = {
title: 'UI/Button',
component: Button,
tags: ['autodocs'],
};
export default meta;

type Story = StoryObj<typeof Button>;

/** Primary */
export const Primary: Story = {
args: { children: '로그인 하기', variant: 'primary', size: 'lg' },
};

/** Secondary */
export const Secondary: Story = {
args: { children: '로그인 하기', variant: 'secondary', size: 'lg' },
};

/** Disabled */
export const Disabled: Story = {
args: { children: '신청 불가', variant: 'disabled', size: 'lg' },
};

/** 승인/거절 아웃라인 버튼 */
export const ApproveReject: Story = {
render: () => (
<div className='flex items-center gap-4'>
<Button variant='approve' size='md'>
승인하기
</Button>
<Button variant='reject' size='md'>
거절하기
</Button>
</div>
),
};

/* Link로 렌더링 (as prop 사용 예) */
export const AsLink: Story = {
args: {
as: Link,
href: '/profile/create',
variant: 'primary',
full: true,
children: '내 프로필 등록하기',
},
};
56 changes: 56 additions & 0 deletions src/components/ui/button/button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { ButtonHTMLAttributes, ElementType } from 'react';

type ButtonProps = {
variant?: 'primary' | 'secondary' | 'disabled' | 'approve' | 'reject';
size?: 'lg' | 'md' | 'sm';
full?: boolean;
as?: ElementType;
} & ButtonHTMLAttributes<HTMLButtonElement> & { [key: string]: unknown };

export default function Button({
variant = 'primary',
size = 'lg',
full = false,
as: Component = 'button',
children,
...props
}: ButtonProps) {
/* 1) 사이즈 */
const sizeClass =
size === 'lg'
? 'h-12 px-4 text-base sm:h-14 sm:px-6 sm:text-lg'
: size === 'md'
? 'h-10 px-4 text-sm sm:h-11 sm:px-5 sm:text-base'
: 'h-8 px-3 text-sm sm:h-9 sm:px-4 sm:text-base';

/* 2) variant에 따른 색상/테두리 */
let variantClass = '';
if (variant === 'primary') {
variantClass = 'bg-[#EA3C12] text-white hover:bg-[#d63810]';
} else if (variant === 'secondary') {
variantClass = 'bg-white text-[#EA3C12] border border-[#EA3C12] hover:bg-[#fff5f2]';
} else if (variant === 'approve') {
variantClass =
'bg-white text-[#0080FF] border border-[#0080FF] hover:bg-[#0080FF] hover:text-white';
} else if (variant === 'reject') {
variantClass =
'bg-white text-[#EA3C12] border border-[#EA3C12] hover:bg-[#EA3C12] hover:text-white';
} else if (variant === 'disabled') {
variantClass = 'bg-[#A9A7AE] text-white cursor-not-allowed';
Copy link
Contributor

Choose a reason for hiding this comment

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

EA3C12 컬러는 red-500 으로 tailwind config 등록이 되어있습니다 :)
혹시 나머지 컬러에 대해서도 globals.css , tailwind config 에 등록해주실 수 있나요??
하드코딩된 컬러값은 다크모드에서 반전할 수가 없어서 버튼컬러 변경이 안될것 같습니다 🥲

disabled 의 A9A7AE 컬러는 gray-400 으로 피그마로 보여지고 있는데 혹시 다른컬러를 선정한 이유가 있으실까요!?
만약 있다면 이것도 450 으로 선언부탁드립니다!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A9A7AE 는 gray-400으로 설정하겠습니다! 그리고 전체적으로 globals.css에 있는걸 적용해서 다시 고쳤습니다 제가 처음에 고려를 못했었습니다

}

/* 3) 공통 */
const baseClass = 'inline-flex items-center justify-center rounded-lg font-medium transition';
Copy link
Contributor

Choose a reason for hiding this comment

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

컴포넌트 렌더링 시점에 계산되는 값이 아닌건 컴포넌트 바깥으로 제외할 수 있을것 같아요!

Copy link
Contributor

Choose a reason for hiding this comment

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

1,2번 스타일도 바깥으로 제외한 뒤 객체로 만들 수 있을것 같습니다!

export const VARIANT_CLASS = {
primary: 스타일~
secondary: 스타일~
} as const;

사용할때는 VARIANT_CLASS[variant]

이런 방식으로도 리팩토링이 가능할것 같습니다 ! 참고해주세요 :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

네 컴포넌트 바깥으로 했습니다!


return (
<Component
className={`${baseClass} ${variantClass} ${sizeClass} ${full ? 'w-full' : ''}`}
{...(Component === 'button'
? { disabled: variant === 'disabled' || props.disabled }
: { 'aria-disabled': variant === 'disabled' || props.disabled })}
{...props} // EX) type="submit" onClick={handleClick} aria-label="로그인 버튼"
>
{children}
</Component>
);
}
Empty file.
Empty file added src/components/ui/input.tsx
Empty file.
Empty file added src/components/ui/modal.tsx
Empty file.
Loading