Skip to content

Commit

Permalink
feat #24 : 디자인 시스템 버튼과 그 외 버튼의 UI를 생성하는 추상화 레이어 분리
Browse files Browse the repository at this point in the history
  • Loading branch information
minh0518 committed Feb 14, 2025
1 parent 8fd5da5 commit 14a9823
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 128 deletions.
33 changes: 12 additions & 21 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,25 @@
import { css } from '@emotion/react';

import { Button } from './common/components/button';
import { KakaoAuthButton } from './common/components/kakaoauthbutton';
import { BaseButton } from './common/components/systembutton';

function App() {
return (
<div>
<Button>Default</Button>
<BaseButton>Default</BaseButton>

<Button variant="destructive" size="sm">
{/* 디자인 시스템 테마 주입 */}
<BaseButton variant="destructive" size="sm">
Small + Destructive
</Button>

<Button
variant="outline"
size="lg"
cssProps={css`
background-color: gray;
border: 10px solid green;
font-size: 1.25rem;
`}
onClick={() => console.log('clicked!')}
>
Large +Outline + Override
</Button>
</BaseButton>

<Button variant="link" asChild>
{/* asChild에 따른 Slot 사용 */}
<BaseButton variant="link" asChild>
<a href="https://example.com" target="_blank" rel="noreferrer">
External Link
</a>
</Button>
</BaseButton>

{/* 내부적으로 고정된 버튼 스타일 및 이벤트 사용 */}
<KakaoAuthButton>카카오 로그인</KakaoAuthButton>
</div>
);
}
Expand Down
90 changes: 1 addition & 89 deletions src/common/components/button/button.styles.ts
Original file line number Diff line number Diff line change
@@ -1,102 +1,14 @@
import { css } from '@emotion/react';

/* 공통(base) 스타일 */
export const baseStyle = css`
export const buttonStyle = css`
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 0.875rem;
font-weight: 500;
white-space: nowrap;
border-radius: 0.375rem;
cursor: pointer;
&:disabled {
pointer-events: none;
opacity: 0.5;
}
svg {
pointer-events: none;
width: 1rem;
height: 1rem;
flex-shrink: 0;
}
`;

/* variant별 스타일 */
export const variants = {
default: css`
background-color: transparent;
color: black;
&:hover {
background-color: #05d;
}
`,
destructive: css`
background-color: #f44;
color: #fff;
&:hover {
background-color: #d22;
}
`,
outline: css`
border: 1px solid #ccc;
background-color: #fff;
&:hover {
background-color: #f9f9f9;
}
`,
secondary: css`
background-color: #f5f5f5;
color: #333;
&:hover {
background-color: #ebebeb;
}
`,
ghost: css`
background-color: transparent;
color: #333;
&:hover {
background-color: rgb(0 0 0 / 8%);
}
`,
link: css`
background-color: transparent;
color: #06f;
text-decoration: underline;
&:hover {
text-decoration: none;
}
`,
};

/* size별 스타일 */
export const sizes = {
default: css`
height: 2.25rem;
padding: 0.5rem 1rem;
`,
sm: css`
height: 2rem;
padding: 0.25rem 0.75rem;
font-size: 0.75rem;
`,
lg: css`
height: 2.5rem;
padding: 0.75rem 1.25rem;
font-size: 1rem;
`,
icon: css`
justify-content: center;
width: 2.25rem;
height: 2.25rem;
padding: 0;
`,
};
24 changes: 6 additions & 18 deletions src/common/components/button/index.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,17 @@
import { forwardRef } from 'react';
import { ButtonHTMLAttributes, forwardRef } from 'react';

import { Interpolation } from '@emotion/react';
import { Slot } from '@radix-ui/react-slot';

import * as styles from './button.styles';

export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
asChild?: boolean;
variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link';
size?: 'default' | 'sm' | 'lg' | 'icon';
cssProps?: Interpolation; // 오버라이딩
}

const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ asChild, variant = 'default', size = 'default', cssProps, ...props }, ref) => {
const Comp = asChild ? Slot : 'button';
return (
<Comp
css={[styles.baseStyle, styles.variants[variant], styles.sizes[size], cssProps]}
ref={ref}
{...props}
/>
);
},
);
const Button = forwardRef<HTMLButtonElement, ButtonProps>(({ asChild, ...props }, ref) => {
const Comp = asChild ? Slot : 'button';
return <Comp css={styles.buttonStyle} ref={ref} {...props} />;
});
Button.displayName = 'Button';

export { Button };
19 changes: 19 additions & 0 deletions src/common/components/kakaoauthbutton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { forwardRef } from 'react';

import { Button, ButtonProps } from '../button';

import * as styles from './kakaoAuthButton.styles';

const KakaoAuthButton = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => {
return (
<Button
onClick={() => console.log('Kakao login!')}
css={styles.kakaoButtonStyle}
ref={ref}
{...props}
/>
);
});
KakaoAuthButton.displayName = 'KakaoAuthButton';

export { KakaoAuthButton };
10 changes: 10 additions & 0 deletions src/common/components/kakaoauthbutton/kakaoAuthButton.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// styles/base-button.styles.ts
import { css } from '@emotion/react';

export const kakaoButtonStyle = css`
width: 100px;
height: 20px;
color: black;
background-color: yellow;
border-radius: 10px;
`;
78 changes: 78 additions & 0 deletions src/common/components/systembutton/BaseButton.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { css } from '@emotion/react';

/* 임시 - variant별 스타일 */
export const variants = {
default: css`
background-color: transparent;
color: black;
&:hover {
background-color: #05d;
}
`,
destructive: css`
background-color: #f44;
color: #fff;
&:hover {
background-color: #d22;
}
`,
outline: css`
border: 1px solid #ccc;
background-color: #fff;
&:hover {
background-color: #f9f9f9;
}
`,
secondary: css`
background-color: #f5f5f5;
color: #333;
&:hover {
background-color: #ebebeb;
}
`,
ghost: css`
background-color: transparent;
color: #333;
&:hover {
background-color: rgb(0 0 0 / 8%);
}
`,
link: css`
background-color: transparent;
color: #06f;
text-decoration: underline;
&:hover {
text-decoration: none;
}
`,
};

/* 임시 - ize별 스타일 */
export const sizes = {
default: css`
height: 2.25rem;
padding: 0.5rem 1rem;
`,
sm: css`
height: 2rem;
padding: 0.25rem 0.75rem;
font-size: 0.75rem;
`,
lg: css`
height: 2.5rem;
padding: 0.75rem 1.25rem;
font-size: 1rem;
`,
icon: css`
justify-content: center;
width: 2.25rem;
height: 2.25rem;
padding: 0;
`,
};
23 changes: 23 additions & 0 deletions src/common/components/systembutton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { forwardRef } from 'react';

import { Button, ButtonProps } from '../button';

import * as styles from './BaseButton.styles';

/** TODO: 디자인 시스템에 따라 추가 예정 */
export type ButtonVariant = 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link';
export type ButtonSize = 'default' | 'sm' | 'lg' | 'icon';

export interface BaseButtonProps extends ButtonProps {
variant?: ButtonVariant;
size?: ButtonSize;
}

const BaseButton = forwardRef<HTMLButtonElement, BaseButtonProps>(
({ variant = 'default', size = 'default', ...props }, ref) => {
return <Button css={[styles.sizes[size], styles.variants[variant]]} ref={ref} {...props} />;
},
);
BaseButton.displayName = 'BaseButton';

export { BaseButton };

0 comments on commit 14a9823

Please sign in to comment.